= this.particleMaxAge){
- this.setExpired();
- }
-
- // This is in radians per tick...
- double omega = Math.signum(speed) * ((Math.PI * 2) / 20 - speed / (20 * radius));
-
- // v = r times omega; therefore the normalised velocity vector needs to be r times the angle increment / 2 pi.
- this.angle += omega;
-
- this.motionY -= 0.04D * (double)this.particleGravity;
- this.motionZ = radius * omega * Math.cos(angle);
- this.motionX = radius * omega * Math.sin(angle);
- this.move(motionX, motionY, motionZ);
-
- if(this.particleAge > this.particleMaxAge / 2){
- this.setAlphaF(
- 1.0F - ((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge);
- }
-
- }
-}
diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleScorch.java b/src/main/java/electroblob/wizardry/client/particle/ParticleScorch.java
new file mode 100644
index 00000000..3523cfa6
--- /dev/null
+++ b/src/main/java/electroblob/wizardry/client/particle/ParticleScorch.java
@@ -0,0 +1,70 @@
+package electroblob.wizardry.client.particle;
+
+import net.minecraft.util.EnumFacing;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+import net.minecraftforge.client.event.TextureStitchEvent;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.relauncher.Side;
+import net.minecraftforge.fml.relauncher.SideOnly;
+
+@SideOnly(Side.CLIENT)
+@Mod.EventBusSubscriber(Side.CLIENT)
+public class ParticleScorch extends ParticleWizardry {
+
+ private static final ResourceLocation[] TEXTURES = generateTextures("scorch", 8);
+
+ public ParticleScorch(World world, double x, double y, double z){
+
+ super(world, x, y, z, TEXTURES[world.rand.nextInt(TEXTURES.length)]);
+
+ this.particleGravity = 0;
+ this.setMaxAge(100 + rand.nextInt(40));
+ this.particleScale *= 2;
+ // Defaults to black (which looks like a 'normal' scorch mark)
+ this.setRBGColorF(0, 0, 0);
+ this.shaded = false;
+ }
+
+ @Override
+ public void setRBGColorF(float r, float g, float b){
+ super.setRBGColorF(r, g, b);
+ this.setFadeColour(0, 0, 0); // Scorch particles fade to black by default
+ }
+
+ @Override
+ public void onUpdate(){
+
+ super.onUpdate();
+
+ // Colour fading (scorch particles do this slightly differently)
+ float ageFraction = Math.min((float)this.particleAge / ((float)this.particleMaxAge * 0.5f), 1);
+ // No longer uses setRBGColorF because that method now also sets the initial values
+ this.particleRed = this.initialRed + (this.fadeRed - this.initialRed) * ageFraction;
+ this.particleGreen = this.initialGreen + (this.fadeGreen - this.initialGreen) * ageFraction;
+ this.particleBlue = this.initialBlue + (this.fadeBlue - this.initialBlue) * ageFraction;
+
+ // Fading
+ if(this.particleAge > this.particleMaxAge/2){
+ this.setAlphaF(1 - ((float)this.particleAge - (float)(this.particleMaxAge/2)) / (float)this.particleMaxAge);
+ }
+
+ EnumFacing facing = EnumFacing.fromAngle(yaw);
+ if(pitch == 90) facing = EnumFacing.UP;
+ if(pitch == -90) facing = EnumFacing.DOWN;
+
+ // Disappears if there is no block behind it (this is the same check used to spawn it)
+ if(!world.getBlockState(new BlockPos(posX, posY, posZ).offset(facing.getOpposite())).getMaterial().isSolid()){
+ this.setExpired();
+ }
+ }
+
+ @SubscribeEvent
+ public static void onTextureStitchEvent(TextureStitchEvent.Pre event){
+ for(ResourceLocation texture : TEXTURES){
+ event.getMap().registerSprite(texture);
+ }
+ }
+}
diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleSnow.java b/src/main/java/electroblob/wizardry/client/particle/ParticleSnow.java
index a18ff4d9..e5de49f9 100644
--- a/src/main/java/electroblob/wizardry/client/particle/ParticleSnow.java
+++ b/src/main/java/electroblob/wizardry/client/particle/ParticleSnow.java
@@ -1,39 +1,36 @@
package electroblob.wizardry.client.particle;
-import electroblob.wizardry.Wizardry;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
+import net.minecraftforge.client.event.TextureStitchEvent;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
-public class ParticleSnow extends ParticleCustomTexture {
+@Mod.EventBusSubscriber(Side.CLIENT)
+public class ParticleSnow extends ParticleWizardry {
- private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID,
- "textures/particle/snow_particles.png");
+ private static final ResourceLocation[] TEXTURES = generateTextures("snow", 4);
public ParticleSnow(World world, double x, double y, double z){
- super(world, x, y, z);
- this.setParticleTextureIndex(rand.nextInt(8));
+
+ super(world, x, y, z, TEXTURES[world.rand.nextInt(TEXTURES.length)]);
+
this.setVelocity(0, -0.02, 0);
this.particleScale *= 0.6f;
this.particleGravity = 0;
this.canCollide = true;
- this.setLifetime(40 + rand.nextInt(10));
+ this.setMaxAge(40 + rand.nextInt(10));
+ // Produces a variety of light blues and whites
+ this.setRBGColorF(0.9f + 0.1f * world.rand.nextFloat(), 0.95f + 0.05f * world.rand.nextFloat(), 1);
}
- @Override
- public ResourceLocation getTexture(){
- return TEXTURE;
- }
-
- @Override
- protected int getXFrames(){
- return 4;
- }
-
- @Override
- protected int getYFrames(){
- return 4;
+ @SubscribeEvent
+ public static void onTextureStitchEvent(TextureStitchEvent.Pre event){
+ for(ResourceLocation texture : TEXTURES){
+ event.getMap().registerSprite(texture);
+ }
}
}
diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleSpark.java b/src/main/java/electroblob/wizardry/client/particle/ParticleSpark.java
index a94103f1..5d879ad0 100644
--- a/src/main/java/electroblob/wizardry/client/particle/ParticleSpark.java
+++ b/src/main/java/electroblob/wizardry/client/particle/ParticleSpark.java
@@ -1,66 +1,55 @@
package electroblob.wizardry.client.particle;
-import org.lwjgl.opengl.GL11;
-
-import electroblob.wizardry.Wizardry;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
+import net.minecraftforge.client.event.TextureStitchEvent;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
-public class ParticleSpark extends ParticleCustomTexture {
+@Mod.EventBusSubscriber(Side.CLIENT)
+public class ParticleSpark extends ParticleWizardry {
- private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID,
- "textures/particle/lightning_particles.png");
+ // 8 different animation strips, 4 in each strip
+ private static final ResourceLocation[][] TEXTURES = generateTextures("lightning", 8, 4);
public ParticleSpark(World world, double x, double y, double z){
- super(world, x, y, z);
- // Multiplied by 4 because the index works slightly differently for spark particles.
- this.setParticleTextureIndex(rand.nextInt(8) * 4);
+
+ super(world, x, y, z, TEXTURES[world.rand.nextInt(TEXTURES.length)]);
+
this.particleScale *= 1.4f;
+ this.setRBGColorF(1, 1, 1);
this.shaded = false;
this.canCollide = false;
- this.setLifetime(3); // Lifetime defaults to 3 (and is very unlikely to be changed)
+ this.setMaxAge(3); // Lifetime defaults to 3 (and is very unlikely to be changed)
}
+
+ // May no longer be necessary, ParticleManager seems to enable blending now
- @Override
- public void onUpdate(){
- super.onUpdate();
- // Well this is handy! Looks like vanilla uses the texture index like this too.
- this.nextTextureIndexX();
- }
-
- @Override
- public ResourceLocation getTexture(){
- return TEXTURE;
- }
-
- @Override
- protected int getXFrames(){
- return 4;
- }
-
- @Override
- protected int getYFrames(){
- return 8;
- }
-
- @Override
- public void applyGLStateChanges(){
- GlStateManager.enableBlend();
- GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
- // TESTME: Are these two actually necessary?
- GlStateManager.disableLighting();
- OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
- }
-
- @Override
- public void undoGLStateChanges(){
- GlStateManager.disableBlend();
- GlStateManager.enableLighting();
+// @Override
+// public void applyGLStateChanges(){
+// GlStateManager.enableBlend();
+// GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+// // TESTME: Are these two actually necessary?
+// GlStateManager.disableLighting();
+// OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
+// }
+//
+// @Override
+// public void undoGLStateChanges(){
+// GlStateManager.disableBlend();
+// GlStateManager.enableLighting();
+// }
+
+ @SubscribeEvent
+ public static void onTextureStitchEvent(TextureStitchEvent.Pre event){
+ for(ResourceLocation[] array : TEXTURES){
+ for(ResourceLocation texture : array){
+ event.getMap().registerSprite(texture);
+ }
+ }
}
}
diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleSparkle.java b/src/main/java/electroblob/wizardry/client/particle/ParticleSparkle.java
index f63bfcfb..4aa64a35 100644
--- a/src/main/java/electroblob/wizardry/client/particle/ParticleSparkle.java
+++ b/src/main/java/electroblob/wizardry/client/particle/ParticleSparkle.java
@@ -1,24 +1,23 @@
package electroblob.wizardry.client.particle;
-import electroblob.wizardry.Wizardry;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
+import net.minecraftforge.client.event.TextureStitchEvent;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
-public class ParticleSparkle extends ParticleCustomTexture {
+@Mod.EventBusSubscriber(Side.CLIENT)
+public class ParticleSparkle extends ParticleWizardry {
- private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID,
- "textures/particle/sparkle_particles.png");
-
- // Implementation of colour fading (perhaps these belong in ParticleWizardry?)
- private float initialRed;
- private float initialGreen;
- private float initialBlue;
+ private static final ResourceLocation[] TEXTURES = generateTextures("sparkle", 11);
public ParticleSparkle(World world, double x, double y, double z){
- super(world, x, y, z);
+
+ super(world, x, y, z, TEXTURES); // This time the textures are all one long animation
+
this.setRBGColorF(1, 1, 1);
this.particleMaxAge = 48 + this.rand.nextInt(12);
this.particleScale *= 0.75f;
@@ -27,30 +26,6 @@ public class ParticleSparkle extends ParticleCustomTexture {
this.shaded = false;
}
- // Overridden to set the initial colour values
- @Override
- public void setRBGColorF(float r, float g, float b){
- super.setRBGColorF(r, g, b);
- initialRed = r;
- initialGreen = g;
- initialBlue = b;
- }
-
- @Override
- public ResourceLocation getTexture(){
- return TEXTURE;
- }
-
- @Override
- protected int getXFrames(){
- return 4;
- }
-
- @Override
- protected int getYFrames(){
- return 4;
- }
-
@Override
public void onUpdate(){
@@ -58,24 +33,14 @@ public class ParticleSparkle extends ParticleCustomTexture {
// Fading
if(this.particleAge > this.particleMaxAge / 2){
- this.setAlphaF(
- 1.0F - ((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge);
+ this.setAlphaF(1 - ((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge);
+ }
+ }
+
+ @SubscribeEvent
+ public static void onTextureStitchEvent(TextureStitchEvent.Pre event){
+ for(ResourceLocation texture : TEXTURES){
+ event.getMap().registerSprite(texture);
}
-
- // Colour fading
- float ageFraction = (float)this.particleAge / (float)this.particleMaxAge;
- // No longer uses setRBGColorF because that method now also sets the initial values
- this.particleRed = this.initialRed + (this.fadeRed - this.initialRed)*ageFraction;
- this.particleGreen = this.initialGreen + (this.fadeGreen - this.initialGreen)*ageFraction;
- this.particleBlue = this.initialBlue + (this.fadeBlue - this.initialBlue)*ageFraction;
-
- this.setParticleTextureIndex((this.particleAge * 11)/this.particleMaxAge);
}
-
- /* As a side note, I see a lot of magic mods with fancy-looking particle effects that really seem to 'glow'. It's
- * actually not that hard - you simply create a reasonably high-res texture with translucency and then set the
- * OpenGL blend function to something like SRC_ALPHA, SRC_ALPHA or ONE, ONE. The thing is... they're not very
- * Minecraft-y. I still maintain that part of wizardry's appeal is that it stays true to the game's pixelated charm,
- * rather than trying to make it something it's not. Still, the newer textures are much better than the defaults I
- * used to use. */
}
diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleTargeted.java b/src/main/java/electroblob/wizardry/client/particle/ParticleTargeted.java
new file mode 100644
index 00000000..80ce3e59
--- /dev/null
+++ b/src/main/java/electroblob/wizardry/client/particle/ParticleTargeted.java
@@ -0,0 +1,105 @@
+package electroblob.wizardry.client.particle;
+
+import javax.annotation.Nullable;
+
+import org.lwjgl.opengl.GL11;
+
+import electroblob.wizardry.Wizardry;
+import net.minecraft.client.renderer.BufferBuilder;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.entity.Entity;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.world.World;
+
+/** Superclass for particles with a second target entity or target position. */
+public abstract class ParticleTargeted extends ParticleWizardry {
+
+ protected double targetX;
+ protected double targetY;
+ protected double targetZ;
+
+ /** The target this particle is linked to. The particle will stretch to touch this entity. */
+ @Nullable
+ protected Entity target = null;
+
+ public ParticleTargeted(World world, double x, double y, double z, ResourceLocation... textures){
+ super(world, x, y, z, textures);
+ }
+
+ @Override
+ public void setTargetPosition(double x, double y, double z){
+ this.targetX = x;
+ this.targetY = y;
+ this.targetZ = z;
+ }
+
+ @Override
+ public void setTargetEntity(Entity target){
+ this.target = target;
+ }
+
+ @Override
+ public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float rotationX, float rotationZ, float rotationYZ,
+ float rotationXY, float rotationXZ){
+
+ if(this.target != null){
+ this.targetX = this.target.posX;
+ this.targetY = this.target.getEntityBoundingBox().minY + target.height/2;
+ this.targetZ = this.target.posZ;
+ }
+
+ if(Double.isNaN(targetX) || Double.isNaN(targetY) || Double.isNaN(targetZ)){
+ Wizardry.logger.warn("Attempted to render a targeted particle, but neither its target entity nor target"
+ + "position was set!");
+ return;
+ }
+
+ // I'm pretty sure these were always static.
+ interpPosX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * (double)partialTicks;
+ interpPosY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * (double)partialTicks;
+ interpPosZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * (double)partialTicks;
+
+ float x = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX);
+ float y = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY);
+ float z = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ);
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(x, y, z);
+
+ double dx = this.targetX - this.posX;
+ double dy = this.targetY - this.posY;
+ double dz = this.targetZ - this.posZ;
+
+ // The distance from origin to endpoint
+ double length = Math.sqrt(dx*dx+dy*dy+dz*dz);
+
+ // Math.atan2 computes within -180 to +180, rather than -90 to +90.
+ float yaw = (float)(180d/Math.PI * Math.atan2(dx, dz));
+ float pitch = (float)(180f/(float)Math.PI * Math.atan(-dy/Math.sqrt(dz*dz+dx*dx)));
+
+ GL11.glRotatef(yaw, 0, 1, 0);
+ GL11.glRotatef(pitch, 1, 0, 0);
+
+ Tessellator tessellator = Tessellator.getInstance();
+
+ this.draw(tessellator, length, partialTicks);
+
+ GlStateManager.popMatrix();
+ }
+
+ /** Called from {@link ParticleTargeted#renderParticle(BufferBuilder, Entity, float, float, float, float, float, float)},
+ * once the appropriate calculations and transformations have been applied, to actually render the particle. Subclasses
+ * override this instead of overriding {@code renderParticle} directly, and inside render the particle along
+ * the z-axis, starting at (0, 0, 0) - it will be translated and rotated automatically.
+ *
+ * N.B. Other than transformations, no GL state changes are applied; these should be done within this method.
+ *
+ * @param tessellator A reference to the tessellator, for convenience.
+ * @param length The distance from the origin to the endpoint for the particle being rendered; the particle should
+ * therefore be rendered between (0, 0, 0) and (0, 0, length) within this method.
+ * @param partialTicks The partial tick time.
+ */
+ protected abstract void draw(Tessellator tessellator, double length, float partialTicks);
+
+}
diff --git a/src/main/java/electroblob/wizardry/client/particle/ParticleWizardry.java b/src/main/java/electroblob/wizardry/client/particle/ParticleWizardry.java
index 607c4da5..62f96e7f 100644
--- a/src/main/java/electroblob/wizardry/client/particle/ParticleWizardry.java
+++ b/src/main/java/electroblob/wizardry/client/particle/ParticleWizardry.java
@@ -1,7 +1,20 @@
package electroblob.wizardry.client.particle;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nullable;
+
+import electroblob.wizardry.Wizardry;
+import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.Particle;
+import net.minecraft.client.renderer.BufferBuilder;
+import net.minecraft.client.renderer.texture.TextureAtlasSprite;
+import net.minecraft.entity.Entity;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
+import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@@ -9,7 +22,7 @@ import net.minecraftforge.fml.relauncher.SideOnly;
* Abstract superclass for all of wizardry's particles. This replaces {@code ParticleCustomTexture} (the functionality of
* which is no longer necessary since wizardry now uses {@code TextureAtlasSprite}s to do the rendering), and fits into
* {@code ParticleBuilder} by exposing all the necessary variables through getters, allowing them to be set on the fly
- * rather than needing to be passed into the constructor.
+ * rather than needing to be passed into the constructor.
*
* The new system is as follows:
*
@@ -17,28 +30,94 @@ import net.minecraftforge.fml.relauncher.SideOnly;
* - Each particle class defines any relevant default values in its constructor, including velocity.
* - The particle builder then overwrites any other values that were set during building.
*
- * This beauty of this system is that there are never any redundant parameters when spawning particles. For example,
+ * This beauty of this system is that there are never any redundant parameters when spawning particles, since you can set
+ * as many or as few parameters as necessary - and in addition, common defaults don't need setting at all. For example,
* snow particles nearly always fall at the same speed, which can now be defined in the particle class and no longer
* needs to be defined when spawning the particle - but importantly, it can still be overridden if desired.
*
* @author Electroblob
- * @since Wizardry 4.2.0
+ * @since Wizardry 4.2.0
* @see electroblob.wizardry.util.ParticleBuilder ParticleBuilder
*/
@SideOnly(Side.CLIENT)
public abstract class ParticleWizardry extends Particle {
+ /** Implementation of animated particles using the TextureAtlasSprite system. Why vanilla doesn't support this I
+ * don't know, considering it too has animated particles. */
+ protected final TextureAtlasSprite[] sprites;
+
/** True if the particle is shaded, false if the particle always renders at full brightness. Defaults to false. */
protected boolean shaded = false;
-
- protected float fadeRed = 1;
- protected float fadeGreen = 1;
- protected float fadeBlue = 0;
- public ParticleWizardry(World world, double x, double y, double z){
+ protected float initialRed;
+ protected float initialGreen;
+ protected float initialBlue;
+
+ protected float fadeRed = 0;
+ protected float fadeGreen = 0;
+ protected float fadeBlue = 0;
+
+ protected float angle;
+ protected double radius = 0;
+ protected double speed = 0;
+
+ /** The entity this particle is linked to. The particle will move with this entity. */
+ @Nullable
+ protected Entity entity = null;
+ /** Coordinates of this particle relative to the linked entity. If the linked entity is null, these are not used. */
+ protected double relativeX, relativeY, relativeZ;
+ /** Velocity of this particle relative to the linked entity. The relative x and z velocities are also used when
+ * the particle has spin to move the centre of rotation. If the linked entity is null and the particle is not
+ * spinning, these are not used and will be {@code NaN}. */
+ protected double relativeMotionX = Double.NaN, relativeMotionY = Double.NaN, relativeMotionZ = Double.NaN;
+ // Note that roll (equivalent to rotating the texture) is effectively handled by particleAngle - although that is
+ // actually the rotation speed and not the angle itself.
+ /** The yaw angle this particle is facing, or {@code NaN} if this particle always faces the viewer (default behaviour). */
+ protected float yaw = Float.NaN;
+ /** The pitch angle this particle is facing, or {@code NaN} if this particle always faces the viewer (default behaviour). */
+ protected float pitch = Float.NaN;
+
+ /**
+ * Creates a new particle in the given world at the given position. All other parameters are set via the various
+ * setter methods ({@link electroblob.wizardry.util.ParticleBuilder ParticleBuilder} deals with all of that anyway).
+ * @param world The world in which to create the particle.
+ * @param x The x-coordinate at which to create the particle.
+ * @param y The y-coordinate at which to create the particle.
+ * @param z The z-coordinate at which to create the particle.
+ * @param textures One or more {@code ResourceLocation}s representing the texture(s) used by this particle. These
+ * must be registered as {@link TextureAtlasSprite}s using {@link TextureStitchEvent} or the textures will be
+ * missing. If more than one {@code ResourceLocation} is specified, the particle will be animated with each texture
+ * shown in order for an equal proportion of the particle's lifetime. If this argument is omitted (or a zero-length
+ * array is given), the particle will use the vanilla system instead (based on the X/Y texture indices).
+ */
+ public ParticleWizardry(World world, double x, double y, double z, ResourceLocation... textures){
+
super(world, x, y, z);
+
+ // Sets the relative coordinates in case they are needed
+ this.relativeX = x;
+ this.relativeY = y;
+ this.relativeZ = z;
+
+ // Deals with the textures
+ if(textures.length > 0){
+
+ sprites = Arrays.stream(textures).map(t -> Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(
+ t.toString())).collect(Collectors.toList()).toArray(new TextureAtlasSprite[0]);
+
+ this.setParticleTexture(sprites[0]);
+
+ }else{
+
+ sprites = new TextureAtlasSprite[0];
+ }
}
+ // ============================================== Parameter Setters ==============================================
+
+ // Setters for parameters that affect all particles - these are implemented in this class (although they may be
+ // reimplemented in subclasses)
+
/** Sets whether the particle should render at full brightness or not. True if the particle is shaded, false if
* the particle always renders at full brightness. Defaults to false.*/
public void setShaded(boolean shaded){
@@ -50,9 +129,9 @@ public abstract class ParticleWizardry extends Particle {
this.particleGravity = gravity ? 1 : 0;
}
- /** Sets this particle's lifetime in ticks.*/
- public void setLifetime(int lifetime){
- this.particleMaxAge = lifetime;
+ /** Sets this particle's collisions. True to enable block collisions, false to disable. Defaults to false.*/
+ public void setCollisions(boolean canCollide){
+ this.canCollide = canCollide;
}
/**
@@ -67,25 +146,252 @@ public abstract class ParticleWizardry extends Particle {
this.motionZ = vz;
}
+ /**
+ * Sets the spin parameters of the particle.
+ * @param radius The spin radius
+ * @param speed The spin speed in rotations per tick
+ */
+ public void setSpin(double radius, double speed){
+ this.radius = radius;
+ this.speed = speed * 2 * Math.PI; // Converts rotations per tick into radians per tick for the trig functions
+ this.angle = this.rand.nextFloat() * (float)Math.PI * 2; // Random start angle TODO: Perhaps this should be specified?
+ // Need to set the start position or the circle won't be centred on the correct position
+ this.relativeX = radius * -MathHelper.cos(angle);
+ this.relativeZ = radius * MathHelper.sin(angle);
+ this.setPosition(posX + relativeX, posY, posZ + relativeZ);
+ this.prevPosX = posX;
+ this.prevPosZ = posZ;
+ // Set these to the correct values
+ this.relativeMotionX = motionX;
+ this.relativeMotionY = motionY;
+ this.relativeMotionZ = motionZ;
+ }
+
+ /**
+ * Links this particle to the given entity. This will cause its position and velocity to be relative to the entity.
+ * @param entity The entity to link to.
+ */
+ public void setEntity(Entity entity){
+ this.entity = entity;
+ // Set these to the correct values
+ if(entity != null){
+ this.setPosition(this.entity.posX + relativeX, this.entity.getEntityBoundingBox().minY
+ + relativeY, this.entity.posZ + relativeZ);
+ this.prevPosX = this.posX;
+ this.prevPosY = this.posY;
+ this.prevPosZ = this.posZ;
+ this.relativeMotionX = motionX;
+ this.relativeMotionY = motionY;
+ this.relativeMotionZ = motionZ;
+ }
+ }
+
+ // Overridden to set the initial colour values
+ /**
+ * Sets the base colour of the particle. Note that this also sets the fade colour so that particles without a
+ * fade colour do not change colour at all; as such fade colour must be set after calling this method.
+ * @param r The red colour component
+ * @param g The green colour component
+ * @param b The blue colour component
+ */
+ @Override
+ public void setRBGColorF(float r, float g, float b){
+ super.setRBGColorF(r, g, b);
+ initialRed = r;
+ initialGreen = g;
+ initialBlue = b;
+ // If fade colour is not specified, it defaults to the main colour - this method is always called first
+ setFadeColour(r, g, b);
+ }
+
/**
* Sets the fade colour of the particle.
* @param r The red colour component
* @param g The green colour component
- * @param g The blue colour component
+ * @param b The blue colour component
*/
public void setFadeColour(float r, float g, float b){
this.fadeRed = r;
this.fadeGreen = g;
this.fadeBlue = b;
}
+
+ /**
+ * Sets the direction this particle faces. This will cause the particle to render facing the given direction.
+ * @param yaw The yaw angle of this particle in degrees, where 0 is [TODO south?].
+ * @param pitch The pitch angle of this particle in degrees, where 0 is horizontal.
+ */
+ public void setFacing(float yaw, float pitch){
+ this.yaw = yaw;
+ this.pitch = pitch;
+ }
+
+ // Setters for parameters that only affect some particles - these are unimplemented in this class because they
+ // doesn't make sense for most particles
+
+ /**
+ * Sets the target position for this particle. This will cause it to stretch to touch the given position,
+ * if supported.
+ * @param x The x-coordinate of the target position.
+ * @param y The y-coordinate of the target position.
+ * @param z The z-coordinate of the target position.
+ */
+ public void setTargetPosition(double x, double y, double z){
+ // Does nothing for normal particles since normal particles always render at a single point
+ }
+
+ /**
+ * Links this particle to the given target. This will cause it to stretch to touch the target, if supported.
+ * @param target The target to link to.
+ */
+ public void setTargetEntity(Entity target){
+ // Does nothing for normal particles since normal particles always render at a single point
+ }
+
+ // ============================================== Method Overrides ==============================================
+
+ @Override
+ public int getFXLayer(){
+ return sprites.length == 0 ? super.getFXLayer() : 1; // This has to be 1 for the TextureAtlasSprites to work
+ }
@Override
public int getBrightnessForRender(float partialTick){
return shaded ? super.getBrightnessForRender(partialTick) : 15728880;
}
+
+ /**
+ * Renders the particle. The mapping names given to the parameters in this method are very misleading; see below for
+ * details of what they actually do. (They're also in a strange order...)
+ * @param buffer The {@code BufferBuilder} object.
+ * @param viewer The entity whose viewpoint the particle is being rendered from; this should always be the
+ * client-side player.
+ * @param partialTicks The partial tick time.
+ * @param lookZ Equal to the cosine of {@code viewer.rotationYaw}. Will be -1 when facing north (negative Z), 0 when
+ * east/west, and +1 when facing south (positive Z). Independent of pitch.
+ * @param lookY Equal to the cosine of {@code viewer.rotationPitch}. Will be 1 when facing directly up or down, and 0
+ * when facing directly horizontally.
+ * @param lookX Equal to the sine of {@code viewer.rotationYaw}. Will be -1 when facing east (positive X), 0 when
+ * facing north/south, and +1 when facing west (negative X). Independent of pitch.
+ * @param lookXY Equal to {@code lookX} times the sine of {@code viewer.rotationPitch}. Will be 0 when facing directly horizontal.
+ * When facing directly up, will be equal to {@code -lookX}. When facing directly down, will be equal to {@code lookX}.
+ * @param lookYZ Equal to {@code -lookZ} times the sine of {@code viewer.rotationPitch}. Will be 0 when facing directly horizontal.
+ * When facing directly up, will be equal to {@code -lookZ}. When facing directly down, will be equal to {@code lookZ}.
+ */
+ @Override
+ public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float lookZ, float lookY,
+ float lookX, float lookXY, float lookYZ){
+
+ if(Float.isNaN(this.yaw) || Float.isNaN(this.pitch)){
+
+ // Normal behaviour (rotates to face the viewer)
+ super.renderParticle(buffer, viewer, partialTicks, lookZ, lookY, lookX, lookXY, lookYZ);
+
+ }else{
+
+ // Specific rotation
+
+ // Copied from ActiveRenderInfo; converts yaw and pitch into the weird parameters used by renderParticle.
+ // The 1st/3rd person distinction has been removed since this has nothing to do with the view angle.
+
+ float degToRadFactor = 0.017453292f; // Conversion from degrees to radians
+
+ float rotationX = MathHelper.cos(yaw * degToRadFactor);
+ float rotationZ = MathHelper.sin(yaw * degToRadFactor);
+ float rotationY = MathHelper.cos(pitch * degToRadFactor);
+ float rotationYZ = -rotationZ * MathHelper.sin(pitch * degToRadFactor);
+ float rotationXY = rotationX * MathHelper.sin(pitch * degToRadFactor);
+
+ super.renderParticle(buffer, viewer, partialTicks, rotationX, rotationY, rotationZ, rotationYZ, rotationXY);
+ }
+ }
+
+ @Override
+ public void onUpdate(){
- /** Simple particle factory interface which takes a world and a position and returns a particle. Used (via lambda
- * expressions) in the client proxy to link particle enum types to actual particle classes. */
+ super.onUpdate();
+
+ // If any of these values is NaN, the particle has neither an entity nor a spin
+ if(!Double.isNaN(relativeMotionX) && !Double.isNaN(relativeMotionY) && !Double.isNaN(relativeMotionZ)){
+
+ // This allows velocity changes from entity linking and spin to stack
+ double vx = relativeMotionX;
+ double vy = relativeMotionY;
+ double vz = relativeMotionZ;
+
+ // Entity linking
+ if(this.entity != null){
+
+ if(this.entity.isDead) this.setExpired();
+
+ this.setPosition(this.entity.posX + relativeX, this.entity.getEntityBoundingBox().minY + relativeY,
+ this.entity.posZ + relativeZ);
+ // Velocity is set so that the renderer will interpolate correctly between ticks
+ vx += this.entity.motionX;
+ vy += this.entity.motionY;
+ vz += this.entity.motionZ;
+ }
+
+ // Spin
+ if(radius > 0){
+ angle += speed;
+ vx += radius * speed * MathHelper.sin(angle);
+ vz += radius * speed * MathHelper.cos(angle);
+ }
+
+ this.relativeX += vx;
+ this.relativeY += vy;
+ this.relativeZ += vz;
+ }
+
+ // Colour fading
+ float ageFraction = (float)this.particleAge / (float)this.particleMaxAge;
+ // No longer uses setRBGColorF because that method now also sets the initial values
+ this.particleRed = this.initialRed + (this.fadeRed - this.initialRed) * ageFraction;
+ this.particleGreen = this.initialGreen + (this.fadeGreen - this.initialGreen) * ageFraction;
+ this.particleBlue = this.initialBlue + (this.fadeBlue - this.initialBlue) * ageFraction;
+
+ // Animation
+ if(sprites.length > 1){
+ // Math.min included for safety so the index cannot possibly exceed the length - 1 an cause an AIOOBE
+ // (which would probably otherwise happen if particleAge == particleMaxAge)
+ this.setParticleTexture(sprites[Math.min((int)(ageFraction * sprites.length), sprites.length - 1)]);
+ }
+ }
+
+ // =============================================== Helper Methods ===============================================
+
+ /** Static helper method that generates an array of n ResourceLocations using the particle file naming convention,
+ * which is the given stem plus an underscore plus the integer index. */
+ public static ResourceLocation[] generateTextures(String stem, int n){
+
+ ResourceLocation[] textures = new ResourceLocation[n];
+
+ for(int i=0; i {
-
- public RenderArc(RenderManager renderManager){
- super(renderManager);
- }
-
- @Override
- public void doRender(EntityArc arc, double x, double y, double z, float viewPitch, float viewYaw) {
-
- GlStateManager.pushMatrix();
- GlStateManager.translate(x, y, z);
- GlStateManager.disableLighting();
- GlStateManager.enableBlend();
- GlStateManager.disableTexture2D();
- GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE);
- OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
-
- Tessellator tessellator = Tessellator.getInstance();
-
- /* Note: A lot of the maths here works on similar triangles and the ratios between them, avoiding too much
- * pythagoras and eliminating the need for any trig. Ratios are used for the positioning of the arc endpoints.
- * Ratios are usually used swapping x and z because the triangles are rotated through 90 degrees. */
-
- double dx = -x;
- double dy = -y;
- double dz = -z;
-
- if(arc.x1 != 0){
-
- dx = arc.x1 - arc.posX;
- dy = arc.y1 - arc.posY;
- dz = arc.z1 - arc.posZ;
-
- // The distance from origin to endpoint
- double arcLength = Math.sqrt(dx*dx+dy*dy+dz*dz);
-
- GL11.glTranslated(dx, dy, dz);
-
- // Math.atan2 computes within -180 to +180, rather than -90 to +90.
- float yaw = (float)(180d/Math.PI * Math.atan2(-dx, -dz));
- float pitch = (float)(180f/(float)Math.PI * Math.atan(dy/Math.sqrt(dz*dz+dx*dx)));
-
- GL11.glRotatef(yaw, 0, 1, 0);
- GL11.glRotatef(pitch, 1, 0, 0);
-
- // The direction of the arc drawn by the tessellator is always along the z axis and is rotated to the
- // correct orientation, that way there isn't a ton of trigonometry and the code is way neater.
-
- boolean freeEnd = arc.freeEnd;
-
- // == To be extracted as constants later ==
- float thickness = 0.04f; // Half the width of the outermost layer
- double maxSegmentLength = 0.6; // Max length of a segment, obviously
- double minSegmentLength = 0.2; // Min length of a segment
- double vertexDither = 0.15; // Max deviation in x or y axis from the centreline
- int maxForkSegments = 3; // Max number of segments a fork can have
- float forkChance = 0.3f; // Chance (as a fraction) that a vertex will have a fork
- int updateTime = 1; // Number of ticks to wait before the arc changes shape again
-
- int numberOfSegments = (int)Math.round(arcLength/maxSegmentLength); // Number of segments
-
- for(int layer=0; layer<3; layer++){
-
- double px=0, py=0, pz=0;
- // Creates a random from the arc's seed field + the number of ticks it has existed/the update period.
- // By using a seed, we can ensure the vertex positions and forks are identical a) for each layer, even
- // though they are rendered sequentially, and b) across many frames (and ticks, if updateTime > 1).
- Random random = new Random(arc.seed + arc.ticksExisted/updateTime);
-
- // numberOfSegments-1 because the last segment is handled separately.
- for(int i=0; i {
-
- private final ResourceLocation[] textures = new ResourceLocation[8];
- private float scale = 1.0f;
-
- public RenderLightningPulse(RenderManager renderManager, float scale){
- super(renderManager);
- for(int i = 0; i < textures.length; i++){
- textures[i] = new ResourceLocation(Wizardry.MODID, "textures/entity/lightning_pulse_" + i + ".png");
- }
- this.scale = scale;
- }
-
- @Override
- public void doRender(EntityLightningPulse entity, double par2, double par4, double par6, float par8, float par9){
-
- GlStateManager.pushMatrix();
- GlStateManager.enableBlend();
- GlStateManager.disableLighting();
- OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
- GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
-
- float yOffset = 0;
-
- GlStateManager.translate((float)par2, (float)par4 + yOffset, (float)par6);
-
- this.bindTexture(textures[entity.ticksExisted]);
- float f6 = 1.0F;
- float f7 = 0.5F;
- float f8 = 0.5F;
-
- GlStateManager.rotate(-90, 1, 0, 0);
-
- GlStateManager.scale(scale, scale, scale);
-
- Tessellator tessellator = Tessellator.getInstance();
- BufferBuilder buffer = tessellator.getBuffer();
- buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
- buffer.pos((double)(0.0F - f7), (double)(0.0F - f8), 0.01).tex(0, 1).endVertex();
- buffer.pos((double)(f6 - f7), (double)(0.0F - f8), 0.01).tex(1, 1).endVertex();
- buffer.pos((double)(f6 - f7), (double)(1.0F - f8), 0.01).tex(1, 0).endVertex();
- buffer.pos((double)(0.0F - f7), (double)(1.0F - f8), 0.01).tex(0, 0).endVertex();
-
- tessellator.draw();
-
- GlStateManager.disableBlend();
- GlStateManager.enableLighting();
- GlStateManager.disableRescaleNormal();
- GlStateManager.popMatrix();
- }
-
- @Override
- protected ResourceLocation getEntityTexture(EntityLightningPulse entity){
- return null;
- }
-
-}
diff --git a/src/main/java/electroblob/wizardry/entity/EntityArc.java b/src/main/java/electroblob/wizardry/entity/EntityArc.java
deleted file mode 100644
index f3c729ae..00000000
--- a/src/main/java/electroblob/wizardry/entity/EntityArc.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package electroblob.wizardry.entity;
-
-import io.netty.buffer.ByteBuf;
-import net.minecraft.entity.Entity;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.world.World;
-import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
-
-public class EntityArc extends Entity implements IEntityAdditionalSpawnData {
-
- public double x1, y1, z1, x2, y2, z2;
- /** The number of ticks the arc lasts for before disappearing. */
- public int lifetime = 3;
- /** False if the arc is locked to an entity, true otherwise. False by default. */
- public boolean freeEnd = false;
- /** A random long value used by the renderer as a seed to generate its vertices from, ensuring they remain the same
- * across multiple frames. Not synced. */
- public final long seed;
-
- public EntityArc(World par1World){
- super(par1World);
- seed = this.rand.nextLong();
- this.ignoreFrustumCheck = true;
- }
-
- public void setEndpointCoords(double x1, double y1, double z1, double x2, double y2, double z2){
- this.x1 = x1;
- this.y1 = y1;
- this.z1 = z1;
- this.x2 = x2;
- this.y2 = y2;
- this.z2 = z2;
- this.setPosition(x2, y2, z2);
- }
-
- @Override
- public void onUpdate(){
- if(this.ticksExisted >= lifetime){
- this.setDead();
- }
- }
-
- protected void entityInit(){
- }
-
- @Override
- protected void readEntityFromNBT(NBTTagCompound nbttagcompound){
-
- }
-
- @Override
- protected void writeEntityToNBT(NBTTagCompound nbttagcompound){
- // Nothing needed here; arc is merely a graphic effect that only exists for a few ticks; as such there is no
- // need to save it.
- }
-
- @Override
- public boolean isInRangeToRenderDist(double distance){
- return true;
- }
-
- @Override
- public void writeSpawnData(ByteBuf data){
- data.writeDouble(this.x1);
- data.writeDouble(this.y1);
- data.writeDouble(this.z1);
- data.writeBoolean(freeEnd);
- }
-
- @Override
- public void readSpawnData(ByteBuf data){
- this.x1 = data.readDouble();
- this.y1 = data.readDouble();
- this.z1 = data.readDouble();
- this.freeEnd = data.readBoolean();
- }
-
-}
diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java b/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java
index c45abe77..4d863e0f 100644
--- a/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java
+++ b/src/main/java/electroblob/wizardry/entity/construct/EntityBlizzard.java
@@ -53,24 +53,13 @@ public class EntityBlizzard extends EntityMagicConstruct {
if(!MagicDamage.isEntityImmune(DamageType.FROST, target))
target.addPotionEffect(new PotionEffect(WizardryPotions.frost, 20, 0));
}
+
}else{
- for(int i=1; i<6; i++){
-
- float brightness = 0.5f + (rand.nextFloat() / 2);
-
- ParticleBuilder.create(Type.BLIZZARD)
- .pos(this.posX, this.posY + rand.nextDouble() * 3, this.posZ)
- .lifetime(100)
- .colour(brightness, brightness + 0.1f, 1.0f)
- .radius(rand.nextDouble() * 2.5d + 0.5d)
- .spawn(world);
-
- ParticleBuilder.create(Type.BLIZZARD)
- .pos(this.posX, this.posY + rand.nextDouble() * 3, this.posZ)
- .lifetime(100)
- .colour(1, 1, 1)
- .radius(rand.nextDouble() * 2.5d + 0.5d)
- .spawn(world);
+
+ for(int i=1; i<12; i++){
+ double speed = (rand.nextBoolean() ? 1 : -1) * 0.1 + 0.05 * rand.nextDouble();
+ ParticleBuilder.create(Type.SNOW).pos(this.posX, this.posY + rand.nextDouble() * 3, this.posZ).vel(0, 0, 0)
+ .time(100).scale(2).spin(rand.nextDouble() * 2.5 + 0.5, speed).spawn(world);
}
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java b/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java
index 6c40f523..7507cbca 100644
--- a/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java
+++ b/src/main/java/electroblob/wizardry/entity/construct/EntityDecay.java
@@ -53,7 +53,7 @@ public class EntityDecay extends EntityMagicConstruct {
ParticleBuilder.create(Type.DARK_MAGIC)
.pos(this.posX + radius * Math.cos(angle), this.posY, this.posZ + radius * Math.sin(angle))
- .colour(brightness, 0, brightness + 0.1f)
+ .clr(brightness, 0, brightness + 0.1f)
.spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java b/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java
index 7ad68328..2a1ab31d 100644
--- a/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java
+++ b/src/main/java/electroblob/wizardry/entity/construct/EntityForcefield.java
@@ -66,8 +66,8 @@ public class EntityForcefield extends EntityMagicConstruct {
ParticleBuilder.create(Type.DUST)
.pos(this.posX + radius * Math.cos(yaw) * Math.cos(pitch), this.posY + 3 + radius * Math.sin(pitch),
this.posZ + radius * Math.sin(yaw) * Math.cos(pitch))
- .lifetime(48 + this.rand.nextInt(12))
- .colour(brightness, brightness, 1.0f).spawn(world);
+ .time(48 + this.rand.nextInt(12))
+ .clr(brightness, brightness, 1.0f).spawn(world);
}
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java b/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java
index 6f174d91..80bec470 100644
--- a/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java
+++ b/src/main/java/electroblob/wizardry/entity/construct/EntityHammer.java
@@ -3,7 +3,6 @@ package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.Wizardry;
-import electroblob.wizardry.entity.EntityArc;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
@@ -98,24 +97,12 @@ public class EntityHammer extends EntityMagicConstruct {
if(this.isValidTarget(target)){
- if(!world.isRemote){
- EntityArc arc = new EntityArc(world);
- arc.setEndpointCoords(this.posX, this.posY + this.height - 0.1, this.posZ, target.posX,
- target.posY + target.height / 2, target.posZ);
- world.spawnEntity(arc);
- }else{
- // TODO: Move all the arc particle (and sound?) stuff into a method in WizardryUtilities
- for(int j=0; j<8; j++){
- ParticleBuilder.create(Type.SPARK)
- .pos(target.posX + world.rand.nextFloat() - 0.5,
- target.getEntityBoundingBox().minY + target.height / 2 + world.rand.nextFloat() * 2 - 1,
- target.posZ + world.rand.nextFloat() - 0.5)
- .spawn(world);
-
- world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, target.posX + rand.nextFloat(),
- target.getEntityBoundingBox().minY + target.height / 2 + rand.nextFloat(),
- target.posZ + rand.nextFloat(), 0, 0, 0);
- }
+ if(world.isRemote){
+
+ ParticleBuilder.create(Type.LIGHTNING).pos(posX, posY + height - 0.1, posZ) .target(target).spawn(world);
+
+ ParticleBuilder.spawnShockParticles(world, target.posX,
+ target.getEntityBoundingBox().minY + target.height, target.posZ);
}
target.playSound(WizardrySounds.SPELL_SPARK, 1.0F, rand.nextFloat() * 0.4F + 1.5F);
diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java b/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java
index 32e893f7..14406109 100644
--- a/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java
+++ b/src/main/java/electroblob/wizardry/entity/construct/EntityHealAura.java
@@ -69,8 +69,8 @@ public class EntityHealAura extends EntityMagicConstruct {
ParticleBuilder.create(Type.SPARKLE)
.pos(this.posX + radius * Math.cos(angle), this.posY, this.posZ + radius * Math.sin(angle))
.vel(0, 0.05, 0)
- .lifetime(48 + this.rand.nextInt(12))
- .colour(1.0f, 1.0f, brightness)
+ .time(48 + this.rand.nextInt(12))
+ .clr(1.0f, 1.0f, brightness)
.spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityLightningPulse.java b/src/main/java/electroblob/wizardry/entity/construct/EntityLightningPulse.java
deleted file mode 100644
index b2d46ab5..00000000
--- a/src/main/java/electroblob/wizardry/entity/construct/EntityLightningPulse.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package electroblob.wizardry.entity.construct;
-
-import net.minecraft.world.World;
-
-@Deprecated // This needs changing into a particle
-public class EntityLightningPulse extends EntityMagicConstruct {
-
- public EntityLightningPulse(World world){
- super(world);
- this.setSize(6, 0.2f);
- }
-
- @Override
- public boolean canRenderOnFire(){
- return false;
- }
-
-}
diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java b/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java
index 62dcea76..589cea82 100644
--- a/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java
+++ b/src/main/java/electroblob/wizardry/entity/construct/EntityLightningSigil.java
@@ -2,7 +2,6 @@ package electroblob.wizardry.entity.construct;
import java.util.List;
-import electroblob.wizardry.entity.EntityArc;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
@@ -11,7 +10,6 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.DamageSource;
-import net.minecraft.util.EnumParticleTypes;
import net.minecraft.world.World;
public class EntityLightningSigil extends EntityMagicConstruct {
@@ -65,25 +63,14 @@ public class EntityLightningSigil extends EntityMagicConstruct {
if(secondaryTarget != target && this.isValidTarget(secondaryTarget)){
- if(!world.isRemote){
- EntityArc arc = new EntityArc(world);
- arc.setEndpointCoords(target.posX, target.posY + target.height / 2, target.posZ,
- secondaryTarget.posX, secondaryTarget.posY + secondaryTarget.height / 2,
+ if(world.isRemote){
+
+ ParticleBuilder.create(Type.LIGHTNING).entity(target)
+ .pos(0, target.height/2, 0).target(secondaryTarget).spawn(world);
+
+ ParticleBuilder.spawnShockParticles(world, secondaryTarget.posX,
+ secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2,
secondaryTarget.posZ);
- world.spawnEntity(arc);
- }else{
- for(int k = 0; k < 8; k++){
- ParticleBuilder.create(Type.SPARK)
- .pos(secondaryTarget.posX + world.rand.nextFloat() - 0.5,
- secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2 + world.rand.nextFloat() * 2 - 1,
- secondaryTarget.posZ + world.rand.nextFloat() - 0.5)
- .spawn(world);
- world.spawnParticle(EnumParticleTypes.SMOKE_LARGE,
- secondaryTarget.posX + world.rand.nextFloat() - 0.5,
- secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2
- + world.rand.nextFloat() * 2 - 1,
- secondaryTarget.posZ + world.rand.nextFloat() - 0.5, 0, 0, 0);
- }
}
secondaryTarget.playSound(WizardrySounds.SPELL_SPARK, 1.0F,
diff --git a/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java b/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java
index f53c2b54..a2c6248c 100644
--- a/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java
+++ b/src/main/java/electroblob/wizardry/entity/construct/EntityTornado.java
@@ -140,12 +140,14 @@ public class EntityTornado extends EntityMagicConstruct {
if(block.getMaterial() == Material.SNOW || block.getMaterial() == Material.CRAFTED_SNOW)
type = Type.SNOW;
- double yPos1 = rand.nextDouble() * 8;
- ParticleBuilder.create(type)
- .pos(this.posX + (rand.nextDouble() * 2 - 1) * (yPos1 / 3 + 0.5d), this.posY + yPos1,
- this.posZ + (rand.nextDouble() * 2 - 1) * (yPos1 / 3 + 0.5d))
- .lifetime(40 + rand.nextInt(10))
- .spawn(world);
+ if(type != null){
+ double yPos1 = rand.nextDouble() * 8;
+ ParticleBuilder.create(type)
+ .pos(this.posX + (rand.nextDouble() * 2 - 1) * (yPos1 / 3 + 0.5d), this.posY + yPos1,
+ this.posZ + (rand.nextDouble() * 2 - 1) * (yPos1 / 3 + 0.5d))
+ .time(40 + rand.nextInt(10))
+ .spawn(world);
+ }
}
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java b/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java
index 38665937..1444d6f9 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntityDecoy.java
@@ -41,14 +41,17 @@ public class EntityDecoy extends EntitySummonedCreature {
@Override
public void onDespawn(){
super.onDespawn();
- for(int i = 0; i < 20; i++){
- ParticleBuilder.create(Type.DUST)
- .pos(this.posX + (this.rand.nextDouble() - 0.5) * this.width, this.getEntityBoundingBox().minY
- + this.rand.nextDouble() * this.height, this.posZ + (this.rand.nextDouble() - 0.5) * this.width)
- .lifetime(40)
- .colour(0.2f, 1.0f, 0.8f)
- .shaded(true)
- .spawn(world);
+
+ if(world.isRemote){
+ for(int i = 0; i < 20; i++){
+ ParticleBuilder.create(Type.DUST)
+ .pos(this.posX + (this.rand.nextDouble() - 0.5) * this.width, this.getEntityBoundingBox().minY
+ + this.rand.nextDouble() * this.height, this.posZ + (this.rand.nextDouble() - 0.5) * this.width)
+ .time(40)
+ .clr(0.2f, 1.0f, 0.8f)
+ .shaded(true)
+ .spawn(world);
+ }
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java b/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java
index 00b4d2e2..356281ea 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntityEvilWizard.java
@@ -221,7 +221,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
// 0.5F.
double y = (double)((float)this.posY - 0.5F + rand.nextFloat());
double z = (double)((float)this.posZ + rand.nextFloat() * 2 - 1.0F);
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1F, 0).colour(1, 1, 0.3f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1F, 0).clr(1, 1, 0.3f).spawn(world);
}
}else{
if(this.getHealth() < 10){
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java b/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java
index 93e25d2b..8003f7f8 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntityIceGiant.java
@@ -99,8 +99,8 @@ public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature
if(this.world.isRemote){
for(int i = 0; i < 30; i++){
float brightness = 0.5f + (rand.nextFloat() / 2);
- ParticleBuilder.create(Type.SPARKLE, this).vel(0, -0.02, 0).lifetime(12 + rand.nextInt(8))
- .colour(brightness, brightness + 0.1f, 1.0f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE, this).vel(0, -0.02, 0).time(12 + rand.nextInt(8))
+ .clr(brightness, brightness + 0.1f, 1.0f).spawn(world);
}
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java b/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java
index 3f2c07e1..5d9fee8b 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntityIceWraith.java
@@ -51,8 +51,8 @@ public class EntityIceWraith extends EntityBlazeMinion {
.pos(this.posX - 0.5d + rand.nextDouble(), this.posY + this.height / 2 - 0.5d + rand.nextDouble(),
this.posZ - 0.5d + rand.nextDouble())
.vel(0, 0.05f, 0)
- .lifetime(20 + rand.nextInt(10))
- .colour(brightness, brightness + 0.1f, 1.0f)
+ .time(20 + rand.nextInt(10))
+ .clr(brightness, brightness + 0.1f, 1.0f)
.spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java b/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java
index fb5364e8..a97c52af 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntityLightningWraith.java
@@ -40,8 +40,8 @@ public class EntityLightningWraith extends EntityBlazeMinion {
if(this.world.isRemote){
for(int i = 0; i < 15; i++){
float brightness = 0.3f + (rand.nextFloat() / 2);
- ParticleBuilder.create(Type.SPARKLE, this).vel(0, 0.05, 0).lifetime(20 + rand.nextInt(10))
- .colour(brightness, brightness + 0.2f, 1.0f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE, this).vel(0, 0.05, 0).time(20 + rand.nextInt(10))
+ .clr(brightness, brightness + 0.2f, 1.0f).spawn(world);
}
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java b/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java
index b182af36..d09a3326 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntityShadowWraith.java
@@ -125,8 +125,8 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell
if(this.world.isRemote){
for(int i = 0; i < 15; i++){
float brightness = rand.nextFloat() * 0.4f;
- ParticleBuilder.create(Type.SPARKLE, this).vel(0, 0.05, 0).lifetime(20 + rand.nextInt(10))
- .colour(brightness, 0.0f, brightness).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE, this).vel(0, 0.05, 0).time(20 + rand.nextInt(10))
+ .clr(brightness, 0.0f, brightness).spawn(world);
}
}
}
@@ -160,10 +160,10 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell
float brightness = rand.nextFloat() * 0.2f;
- ParticleBuilder.create(Type.SPARKLE, this).vel(0, 0.05, 0).lifetime(20 + rand.nextInt(10))
- .colour(brightness, 0.0f, brightness).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE, this).vel(0, 0.05, 0).time(20 + rand.nextInt(10))
+ .clr(brightness, 0.0f, brightness).spawn(world);
- ParticleBuilder.create(Type.DARK_MAGIC, this).colour(0.1f, 0.0f, 0.0f).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC, this).clr(0.1f, 0.0f, 0.0f).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java
index b2a2c8fa..e0275389 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntitySilverfishMinion.java
@@ -82,7 +82,7 @@ public class EntitySilverfishMinion extends EntitySilverfish implements ISummone
for(int i = 0; i < 15; i++){
ParticleBuilder.create(Type.DARK_MAGIC)
.pos(this.posX + this.rand.nextFloat(), this.posY + this.rand.nextFloat(), this.posZ + this.rand.nextFloat())
- .colour(0.3f, 0.3f, 0.3f)
+ .clr(0.3f, 0.3f, 0.3f)
.spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java b/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java
index 23b7824b..328e988c 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntitySpiderMinion.java
@@ -110,7 +110,7 @@ public class EntitySpiderMinion extends EntityCaveSpider implements ISummonedCre
for(int i = 0; i < 15; i++){
ParticleBuilder.create(Type.DARK_MAGIC)
.pos(this.posX + this.rand.nextFloat(), this.posY + this.rand.nextFloat(), this.posZ + this.rand.nextFloat())
- .colour(0.1f, 0.2f, 0.0f)
+ .clr(0.1f, 0.2f, 0.0f)
.spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySpiritHorse.java b/src/main/java/electroblob/wizardry/entity/living/EntitySpiritHorse.java
index efd656d0..67284bde 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntitySpiritHorse.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntitySpiritHorse.java
@@ -120,7 +120,7 @@ public class EntitySpiritHorse extends EntityHorse {
double x = this.posX - this.width / 2 + this.rand.nextFloat() * width;
double y = this.posY + this.height * this.rand.nextFloat() + 0.2f;
double z = this.posZ - this.width / 2 + this.rand.nextFloat() * width;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).colour(0.8f, 0.8f, 1.0f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).clr(0.8f, 0.8f, 1.0f).spawn(world);
}
}
@@ -158,7 +158,7 @@ public class EntitySpiritHorse extends EntityHorse {
double x = this.posX - this.width / 2 + this.rand.nextFloat() * width;
double y = this.posY + this.height * this.rand.nextFloat() + 0.2f;
double z = this.posZ - this.width / 2 + this.rand.nextFloat() * width;
- ParticleBuilder.create(Type.DUST).pos(x, y, z).colour(0.8f, 0.8f, 1.0f).shaded(true).spawn(world);
+ ParticleBuilder.create(Type.DUST).pos(x, y, z).clr(0.8f, 0.8f, 1.0f).shaded(true).spawn(world);
}
// Spirit horse disappears a short time after being dismounted.
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntitySpiritWolf.java b/src/main/java/electroblob/wizardry/entity/living/EntitySpiritWolf.java
index db5c7ab3..f18601f9 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntitySpiritWolf.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntitySpiritWolf.java
@@ -89,7 +89,7 @@ public class EntitySpiritWolf extends EntityWolf {
double x = this.posX - this.width / 2 + this.rand.nextFloat() * width;
double y = this.posY + this.height * this.rand.nextFloat() + 0.2f;
double z = this.posZ - this.width / 2 + this.rand.nextFloat() * width;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).colour(0.8f, 0.8f, 1.0f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).clr(0.8f, 0.8f, 1.0f).spawn(world);
}
}
@@ -103,7 +103,7 @@ public class EntitySpiritWolf extends EntityWolf {
double x = this.posX - this.width / 2 + this.rand.nextFloat() * width;
double y = this.posY + this.height * this.rand.nextFloat() + 0.2f;
double z = this.posZ - this.width / 2 + this.rand.nextFloat() * width;
- ParticleBuilder.create(Type.DUST).pos(x, y, z).colour(0.8f, 0.8f, 1.0f).shaded(true).spawn(world);
+ ParticleBuilder.create(Type.DUST).pos(x, y, z).clr(0.8f, 0.8f, 1.0f).shaded(true).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java b/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java
index 602a6941..29776335 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntityStormElemental.java
@@ -148,8 +148,9 @@ public class EntityStormElemental extends EntitySummonedCreature implements ISpe
float brightness = rand.nextFloat() * 0.2f;
double dy = this.rand.nextDouble() * (double)this.height;
- ParticleBuilder.create(Type.SPARKLE_ROTATING).pos(this.posX, this.posY + dy, this.posZ)
- .lifetime(20 + rand.nextInt(10)).colour(0, brightness, brightness).radius(0.2f + 0.5f * dy).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(this.posX, this.posY + dy, this.posZ)
+ .time(20 + rand.nextInt(10)).clr(0, brightness, brightness)//.entity(this)
+ .spin(0.2 + 0.5 * dy, 0.1 + 0.05 * world.rand.nextDouble()).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java b/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java
index 7214304e..1e71a7c2 100644
--- a/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java
+++ b/src/main/java/electroblob/wizardry/entity/living/EntityWizard.java
@@ -310,7 +310,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
// 0.5F.
double y = (double)((float)this.posY - 0.5F + rand.nextFloat());
double z = (double)((float)this.posZ + rand.nextFloat() * 2 - 1.0F);
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1F, 0).colour(1, 1, 0.3f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1F, 0).clr(1, 1, 0.3f).spawn(world);
}
}else{
if(this.getHealth() < 10){
diff --git a/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java b/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java
index 1b6a0069..a3bbfcee 100644
--- a/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java
+++ b/src/main/java/electroblob/wizardry/entity/living/ISummonedCreature.java
@@ -308,7 +308,7 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData {
if(this.hasParticleEffect() && thisEntity.world.isRemote && thisEntity.world.rand.nextInt(8) == 0)
ParticleBuilder.create(Type.DARK_MAGIC)
.pos(thisEntity.posX, thisEntity.posY + thisEntity.world.rand.nextDouble() * 1.5, thisEntity.posZ)
- .colour(0.1f, 0.0f, 0.0f)
+ .clr(0.1f, 0.0f, 0.0f)
.spawn(thisEntity.world);
}
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java
index 43e81c5e..d9aee1e5 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityDarknessOrb.java
@@ -47,10 +47,10 @@ public class EntityDarknessOrb extends EntityMagicProjectile {
float brightness = rand.nextFloat() * 0.2f;
- ParticleBuilder.create(Type.SPARKLE, this).lifetime(20 + rand.nextInt(10))
- .colour(brightness, 0.0f, brightness).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE, this).time(20 + rand.nextInt(10))
+ .clr(brightness, 0.0f, brightness).spawn(world);
- ParticleBuilder.create(Type.DARK_MAGIC, this).colour(0.1f, 0.0f, 0.0f).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC, this).clr(0.1f, 0.0f, 0.0f).spawn(world);
}
if(this.ticksExisted > 150){
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java
index 1ab9c0f0..146b0c4e 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityDart.java
@@ -36,7 +36,7 @@ public class EntityDart extends EntityMagicArrow {
@Override
public void tickInAir(){
if(this.world.isRemote){
- ParticleBuilder.create(Type.LEAF, this).lifetime(10 + rand.nextInt(5)).spawn(world);
+ ParticleBuilder.create(Type.LEAF, this).time(10 + rand.nextInt(5)).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java
index d6e207c5..32c42bf3 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityFirebomb.java
@@ -39,16 +39,19 @@ public class EntityFirebomb extends EntityBomb {
// Particle effect
if(world.isRemote){
- this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
-
+ ParticleBuilder.create(Type.FLASH).pos(this.getPositionVector()).scale(5 * blastMultiplier).clr(1, 0.6f, 0)
+ .spawn(world);
+
for(int i = 0; i < 60 * blastMultiplier; i++){
ParticleBuilder.create(Type.MAGIC_FIRE, rand, posX, posY, posZ, 2*blastMultiplier, false)
- .lifetime(15 + rand.nextInt(5)).scale(2 + rand.nextFloat()).spawn(world);
+ .time(15 + rand.nextInt(5)).scale(2 + rand.nextFloat()).spawn(world);
ParticleBuilder.create(Type.DARK_MAGIC, rand, posX, posY, posZ, 2*blastMultiplier, false)
- .colour(1.0f, 0.2f + rand.nextFloat() * 0.4f, 0.0f).spawn(world);
+ .clr(1.0f, 0.2f + rand.nextFloat() * 0.4f, 0.0f).spawn(world);
}
+
+ this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
}
if(!this.world.isRemote){
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java
index 89738294..8fcf251d 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceArrow.java
@@ -1,6 +1,8 @@
package electroblob.wizardry.entity.projectile;
import electroblob.wizardry.util.MagicDamage.DamageType;
+import electroblob.wizardry.util.ParticleBuilder;
+import electroblob.wizardry.util.ParticleBuilder.Type;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.SoundEvents;
import net.minecraft.world.World;
@@ -15,6 +17,8 @@ public class EntityForceArrow extends EntityMagicArrow {
@Override
public void onEntityHit(EntityLivingBase entityHit){
this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST, 1.0F, 1.0F);
+ if(this.world.isRemote)
+ ParticleBuilder.create(Type.FLASH).pos(posX, posY, posZ).scale(1.3f).clr(0.75f, 1, 0.85f).spawn(world);
}
@Override
@@ -25,6 +29,13 @@ public class EntityForceArrow extends EntityMagicArrow {
@Override
public void onBlockHit(){
this.playSound(SoundEvents.ENTITY_FIREWORK_BLAST, 1.0F, 1.0F);
+ if(this.world.isRemote){
+ // Gets a position slightly away from the block hit so the particle doesn't get cut in half by the block face
+ Vec3d vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(0.15));
+ ParticleBuilder.create(Type.FLASH).pos(vec).scale(1.3f).clr(0.75f, 1, 0.85f).spawn(world);
+ vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET));
+ ParticleBuilder.create(Type.SCORCH).pos(vec).face(hit.sideHit).clr(0, 1, 0.5f).spawn(world);
+ }
}
@Override
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java
index 5c554aa2..73373a40 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityForceOrb.java
@@ -31,8 +31,8 @@ public class EntityForceOrb extends EntityBomb {
if(this.world.isRemote){
for(int j = 0; j < 20; j++){
float brightness = 0.5f + (rand.nextFloat() / 2);
- ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 0.25, true).lifetime(6)
- .colour(brightness, 1.0f, brightness + 0.2f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 0.25, true).time(6)
+ .clr(brightness, 1.0f, brightness + 0.2f).spawn(world);
}
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
}
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java
index 25282d28..1f35f8d6 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceCharge.java
@@ -47,11 +47,11 @@ public class EntityIceCharge extends EntityBomb {
for(int i = 0; i < 30 * blastMultiplier; i++){
ParticleBuilder.create(Type.ICE, rand, this.posX, this.posY, this.posZ, 2 * blastMultiplier, false)
- .lifetime(35).gravity(true).spawn(world);
+ .time(35).gravity(true).spawn(world);
float brightness = 0.4f + rand.nextFloat() * 0.5f;
ParticleBuilder.create(Type.DARK_MAGIC, rand, this.posX, this.posY, this.posZ, 2 * blastMultiplier, false)
- .colour(brightness, brightness + 0.1f, 1.0f).spawn(world);
+ .clr(brightness, brightness + 0.1f, 1.0f).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java
index 5666ca18..1863f343 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceLance.java
@@ -46,7 +46,7 @@ public class EntityIceLance extends EntityMagicArrow {
if(this.world.isRemote){
for(int j = 0; j < 10; j++){
ParticleBuilder.create(Type.ICE, this.rand, this.posX, this.posY, this.posZ, 0.5, true)
- .lifetime(20 + rand.nextInt(10)).gravity(true).spawn(world);
+ .time(20 + rand.nextInt(10)).gravity(true).spawn(world);
}
}
// Parameters for sound: sound event name, volume, pitch.
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java
index 936acacc..c4d42bfa 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityIceShard.java
@@ -41,9 +41,13 @@ public class EntityIceShard extends EntityMagicArrow {
public void onBlockHit(){
// Adds a particle effect when the ice shard hits a block.
if(this.world.isRemote){
+ // Gets a position slightly away from the block hit so the particle doesn't get cut in half by the block face
+ Vec3d vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(0.15));
+ ParticleBuilder.create(Type.FLASH).pos(vec).clr(0.75f, 1, 1).spawn(world);
+
for(int j = 0; j < 10; j++){
ParticleBuilder.create(Type.ICE, this.rand, this.posX, this.posY, this.posZ, 0.5, true)
- .lifetime(20 + rand.nextInt(10)).gravity(true).spawn(world);
+ .time(20 + rand.nextInt(10)).gravity(true).spawn(world);
}
}
// Parameters for sound: sound event name, volume, pitch.
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java
index 8e5d38dc..63857276 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityLightningArrow.java
@@ -32,6 +32,12 @@ public class EntityLightningArrow extends EntityMagicArrow {
}
this.playSound(WizardrySounds.SPELL_SPARK, 1.0F, 1.0F);
+ @Override
+ public void onBlockHit(RayTraceResult hit){
+ if(this.world.isRemote){
+ Vec3d vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(WizardryUtilities.ANTI_Z_FIGHTING_OFFSET));
+ ParticleBuilder.create(Type.SCORCH).pos(vec).face(hit.sideHit).clr(0.4f, 0.8f, 1).scale(0.6f).spawn(world);
+ }
}
@Override
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java
index bf2e5166..0485db50 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicArrow.java
@@ -201,8 +201,10 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
/** Called when the projectile hits an entity. Override to add potion effects and such like. */
protected void onEntityHit(EntityLivingBase entityHit){}
- /** Called when the projectile hits a block. Override to add sound effects and such like. */
- protected void onBlockHit(){}
+ /** Called when the projectile hits a block. Override to add sound effects and such like.
+ * @param hit A vector representing the exact coordinates of the hit; use this to centre particle effects, for
+ * example. */
+ protected void onBlockHit(RayTraceResult hit){}
@Override
public void onUpdate(){
@@ -390,7 +392,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
this.inGround = true;
this.arrowShake = 7;
- this.onBlockHit();
+ this.onBlockHit(raytraceresult);
if(this.stuckInBlock.getMaterial() != Material.AIR){
this.stuckInBlock.getBlock().onEntityCollidedWithBlock(this.world, raytraceresult.getBlockPos(),
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java
index 60a3e60b..676ba719 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityMagicMissile.java
@@ -4,9 +4,14 @@ import electroblob.wizardry.util.ParticleBuilder;
import electroblob.wizardry.util.ParticleBuilder.Type;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.SoundEvents;
+import net.minecraft.util.math.RayTraceResult;
+import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class EntityMagicMissile extends EntityMagicArrow {
+
+ /** The number of ticks the magic missile flies for before vanishing; effectively determines its range. */
+ private static final int LIFETIME = 12;
/** Creates a new magic missile in the given world. */
public EntityMagicMissile(World world){
@@ -26,25 +31,32 @@ public class EntityMagicMissile extends EntityMagicArrow {
}
@Override
- public void onBlockHit(){
- if(this.world.isRemote) spawnImpactParticles();
- }
-
- private void spawnImpactParticles(){
- ParticleBuilder.create(Type.FLASH).pos(posX, posY, posZ).colour(0.5f + rand.nextFloat()/2, 0.5f + rand.nextFloat()/2,
- 0.5f + rand.nextFloat()/2).spawn(world);
+ public void onBlockHit(RayTraceResult hit){
+ if(this.world.isRemote){
+ // Gets a position slightly away from the block hit so the particle doesn't get cut in half by the block face
+ Vec3d vec = hit.hitVec.add(new Vec3d(hit.sideHit.getDirectionVec()).scale(0.15));
+ ParticleBuilder.create(Type.FLASH).pos(vec).clr(1, 1, 0.65f).fade(0.85f, 0.5f, 0.8f).spawn(world);
+ }
}
@Override
public void tickInAir(){
- if(this.ticksExisted > 20){
+ if(this.ticksExisted > LIFETIME){
this.setDead();
}
if(this.world.isRemote){
- ParticleBuilder.create(Type.SPARKLE).pos(this.posX, this.posY, this.posZ).lifetime(20 + rand.nextInt(10))
- .colour(0.5f + (rand.nextFloat() / 2), 0.5f + (rand.nextFloat() / 2), 0.5f + (rand.nextFloat() / 2)).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 0.03, true).clr(1, 1, 0.65f).fade(0.7f, 0, 1)
+ .time(20 + rand.nextInt(10)).spawn(world);
+
+ if(this.ticksExisted > 1){ // Don't spawn particles behind where it started!
+ double x = posX - motionX/2;
+ double y = posY - motionY/2;
+ double z = posZ - motionZ/2;
+ ParticleBuilder.create(Type.SPARKLE, rand, x, y, z, 0.03, true).clr(1, 1, 0.65f).fade(0.7f, 0, 1)
+ .time(20 + rand.nextInt(10)).spawn(world);
+ }
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java
index c2ae3d54..5dfd2f8e 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntityPoisonBomb.java
@@ -41,13 +41,17 @@ public class EntityPoisonBomb extends EntityBomb {
// Particle effect
if(world.isRemote){
+
+ ParticleBuilder.create(Type.FLASH).pos(this.getPositionVector()).scale(5 * blastMultiplier)
+ .clr(0.2f + rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
+
for(int i = 0; i < 60 * blastMultiplier; i++){
- ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 2*blastMultiplier, false).lifetime(35)
- .colour(0.2f + rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 2*blastMultiplier, false).time(35)
+ .clr(0.2f + rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
ParticleBuilder.create(Type.DARK_MAGIC, rand, posX, posY, posZ, 2*blastMultiplier, false)
- .colour(0.2f + rand.nextFloat() * 0.2f, 0.8f, 0.0f).spawn(world);
+ .clr(0.2f + rand.nextFloat() * 0.2f, 0.8f, 0.0f).spawn(world);
}
// Spawning this after the other particles fixes the rendering colour bug. It's a bit of a cheat, but it
// works pretty well.
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java
index 61dcf727..e19592a6 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntitySmokeBomb.java
@@ -27,7 +27,11 @@ public class EntitySmokeBomb extends EntityBomb {
// Particle effect
if(world.isRemote){
+
+ ParticleBuilder.create(Type.FLASH).pos(this.getPositionVector()).scale(5 * blastMultiplier).clr(0, 0, 0).spawn(world);
+
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
+
for(int i = 0; i < 60 * blastMultiplier; i++){
this.world.spawnParticle(EnumParticleTypes.SMOKE_LARGE,
@@ -37,7 +41,7 @@ public class EntitySmokeBomb extends EntityBomb {
float brightness = rand.nextFloat() * 0.3f;
ParticleBuilder.create(Type.DARK_MAGIC, rand, posX, posY, posZ, 2*blastMultiplier, false)
- .colour(brightness, brightness, brightness).spawn(world);
+ .clr(brightness, brightness, brightness).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java b/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java
index 6b8a92b1..28ddbf8a 100644
--- a/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java
+++ b/src/main/java/electroblob/wizardry/entity/projectile/EntitySparkBomb.java
@@ -2,11 +2,11 @@ package electroblob.wizardry.entity.projectile;
import java.util.List;
-import electroblob.wizardry.entity.EntityArc;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.ParticleBuilder;
+import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
@@ -65,19 +65,14 @@ public class EntitySparkBomb extends EntityBomb {
if(!this.world.isRemote){
- EntityArc arc = new EntityArc(this.world);
- arc.setEndpointCoords(this.posX, this.posY, this.posZ, target.posX, target.posY + target.height / 2,
- target.posZ);
- this.world.spawnEntity(arc);
-
- target.playSound(WizardrySounds.SPELL_SPARK, 1.0F, rand.nextFloat() * 0.4F + 1.5F);
+ target.playSound(WizardrySounds.ENTITY_SPARK_BOMB_CHAIN, 1.0F, rand.nextFloat() * 0.4F + 1.5F);
target.attackEntityFrom(
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK),
5.0f * damageMultiplier);
}else{
- // Particle effect
+ ParticleBuilder.create(Type.LIGHTNING).pos(this.getPositionVector()).target(target).spawn(world);
ParticleBuilder.spawnShockParticles(world, target.posX, target.getEntityBoundingBox().minY + target.height/2, target.posZ);
}
}
diff --git a/src/main/java/electroblob/wizardry/potion/PotionFrost.java b/src/main/java/electroblob/wizardry/potion/PotionFrost.java
index 7cb709e2..2733ded4 100644
--- a/src/main/java/electroblob/wizardry/potion/PotionFrost.java
+++ b/src/main/java/electroblob/wizardry/potion/PotionFrost.java
@@ -40,7 +40,6 @@ public class PotionFrost extends Potion implements ICustomPotionParticles {
@Override
public void spawnCustomParticle(World world, double x, double y, double z){
- ParticleBuilder.create(Type.SNOW).pos(x, y, z).lifetime(15 + world.rand.nextInt(5)).spawn(world);
}
@Override
@@ -55,6 +54,7 @@ public class PotionFrost extends Potion implements ICustomPotionParticles {
public void renderHUDEffect(int x, int y, PotionEffect effect, net.minecraft.client.Minecraft mc, float alpha){
mc.renderEngine.bindTexture(ICON);
WizardryUtilities.drawTexturedRect(x + 3, y + 3, 0, 0, 18, 18, 18, 18);
+ ParticleBuilder.create(Type.SNOW).pos(x, y, z).time(15 + world.rand.nextInt(5)).spawn(world);
}
@SubscribeEvent
diff --git a/src/main/java/electroblob/wizardry/spell/Arc.java b/src/main/java/electroblob/wizardry/spell/Arc.java
index 296b3355..e543790d 100644
--- a/src/main/java/electroblob/wizardry/spell/Arc.java
+++ b/src/main/java/electroblob/wizardry/spell/Arc.java
@@ -30,11 +30,10 @@ public class Arc extends SpellRay {
if(WizardryUtilities.isLiving(target)){
- if(!world.isRemote){
- EntityArc arc = new EntityArc(world);
- arc.setEndpointCoords(caster.posX, caster.posY + 1, caster.posZ, target.posX, target.posY + target.height / 2, target.posZ);
- world.spawnEntity(arc);
- }else{
+ if(world.isRemote){
+ // Rather neatly, the entity can be set here and if it's null nothing will happen.
+ ParticleBuilder.create(Type.LIGHTNING).entity(caster)
+ .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(target).spawn(world);
ParticleBuilder.spawnShockParticles(world, target.posX, target.getEntityBoundingBox().minY + target.height/2, target.posZ);
}
diff --git a/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java b/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java
index 650e1966..099943c5 100644
--- a/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java
+++ b/src/main/java/electroblob/wizardry/spell/ArcaneJammer.java
@@ -60,7 +60,7 @@ public class ArcaneJammer extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)).colour(0.9f, 0.3f, 0.7f)
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(12 + world.rand.nextInt(8)).clr(0.9f, 0.3f, 0.7f)
.spawn(world);
}
diff --git a/src/main/java/electroblob/wizardry/spell/Banish.java b/src/main/java/electroblob/wizardry/spell/Banish.java
index 469334a2..f1523866 100644
--- a/src/main/java/electroblob/wizardry/spell/Banish.java
+++ b/src/main/java/electroblob/wizardry/spell/Banish.java
@@ -89,7 +89,7 @@ public class Banish extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
world.spawnParticle(EnumParticleTypes.PORTAL, x, y - 0.5, z, 0, 0, 0);
- ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.2f, 0, 0.2f).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.2f, 0, 0.2f).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/ChainLightning.java b/src/main/java/electroblob/wizardry/spell/ChainLightning.java
index ca23af59..8e6bfb72 100644
--- a/src/main/java/electroblob/wizardry/spell/ChainLightning.java
+++ b/src/main/java/electroblob/wizardry/spell/ChainLightning.java
@@ -102,12 +102,11 @@ public class ChainLightning extends SpellRay {
target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), damage);
}
- if(!world.isRemote){
- EntityArc arc = new EntityArc(world);
- arc.setEndpointCoords(caster.posX, caster.getEntityBoundingBox().minY + caster.height / 2, caster.posZ,
- target.posX, target.getEntityBoundingBox().minY + target.height / 2, target.posZ);
- world.spawnEntity(arc);
- }else{
+ if(world.isRemote){
+
+ ParticleBuilder.create(Type.LIGHTNING).entity(caster)
+ .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(target).spawn(world);
+
ParticleBuilder.spawnShockParticles(world, target.posX, target.getEntityBoundingBox().minY + target.height/2, target.posZ);
}
diff --git a/src/main/java/electroblob/wizardry/spell/Clairvoyance.java b/src/main/java/electroblob/wizardry/spell/Clairvoyance.java
index 6f74e00a..0b582f15 100644
--- a/src/main/java/electroblob/wizardry/spell/Clairvoyance.java
+++ b/src/main/java/electroblob/wizardry/spell/Clairvoyance.java
@@ -127,7 +127,7 @@ public class Clairvoyance extends Spell {
(nextPoint.x - point.x) / (float)PARTICLE_MOVEMENT_INTERVAL,
(nextPoint.y - point.y) / (float)PARTICLE_MOVEMENT_INTERVAL,
(nextPoint.z - point.z) / (float)PARTICLE_MOVEMENT_INTERVAL)
- .lifetime((int)(1800 * durationMultiplier)).colour(0, 1, 0.3f).spawn(world);
+ .time((int)(1800 * durationMultiplier)).clr(0, 1, 0.3f).spawn(world);
path.incrementPathIndex();
path.incrementPathIndex();
@@ -136,7 +136,7 @@ public class Clairvoyance extends Spell {
point = path.getFinalPathPoint();
ParticleBuilder.create(Type.PATH).pos(point.x + 0.5, point.y + 0.5, point.z + 0.5)
- .lifetime((int)(1800 * durationMultiplier)).colour(1, 1, 1).spawn(world);
+ .time((int)(1800 * durationMultiplier)).clr(1, 1, 1).spawn(world);
}
@SubscribeEvent
diff --git a/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java b/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java
index 4936395a..d6e73fb2 100644
--- a/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java
+++ b/src/main/java/electroblob/wizardry/spell/CurseOfSoulbinding.java
@@ -54,9 +54,9 @@ public class CurseOfSoulbinding extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
- ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.4f, 0, 0).spawn(world);
- ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.1f, 0, 0).spawn(world);
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)).colour(1, 0.8f, 1).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.4f, 0, 0).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.1f, 0, 0).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(12 + world.rand.nextInt(8)).clr(1, 0.8f, 1).spawn(world);
}
@SubscribeEvent
diff --git a/src/main/java/electroblob/wizardry/spell/Entrapment.java b/src/main/java/electroblob/wizardry/spell/Entrapment.java
index 2b7f8c30..931a230e 100644
--- a/src/main/java/electroblob/wizardry/spell/Entrapment.java
+++ b/src/main/java/electroblob/wizardry/spell/Entrapment.java
@@ -63,7 +63,7 @@ public class Entrapment extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
world.spawnParticle(EnumParticleTypes.PORTAL, x, y - 0.5, z, 0, 0, 0);
- ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.1f, 0, 0).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.1f, 0, 0).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java b/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java
index f157a8c2..1c940d4e 100644
--- a/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java
+++ b/src/main/java/electroblob/wizardry/spell/FlamingWeapon.java
@@ -53,7 +53,7 @@ public class FlamingWeapon extends Spell {
double x = caster.posX + world.rand.nextDouble() * 2 - 1;
double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble();
double z = caster.posZ + world.rand.nextDouble() * 2 - 1;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.9f, 0.7f, 1).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(0.9f, 0.7f, 1).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/Flight.java b/src/main/java/electroblob/wizardry/spell/Flight.java
index 70183b00..eb36ceff 100644
--- a/src/main/java/electroblob/wizardry/spell/Flight.java
+++ b/src/main/java/electroblob/wizardry/spell/Flight.java
@@ -41,11 +41,11 @@ public class Flight extends Spell {
double x = caster.posX - 1 + world.rand.nextDouble() * 2;
double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble();
double z = caster.posZ - 1 + world.rand.nextDouble() * 2;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).lifetime(15).colour(0.8f, 1, 0.5f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).time(15).clr(0.8f, 1, 0.5f).spawn(world);
x = caster.posX - 1 + world.rand.nextDouble() * 2;
y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble();
z = caster.posZ - 1 + world.rand.nextDouble() * 2;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).lifetime(15).colour(1, 1, 1).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).time(15).clr(1, 1, 1).spawn(world);
}
if(ticksInUse % 24 == 0){
diff --git a/src/main/java/electroblob/wizardry/spell/FontOfMana.java b/src/main/java/electroblob/wizardry/spell/FontOfMana.java
index df6f46af..6963c42f 100644
--- a/src/main/java/electroblob/wizardry/spell/FontOfMana.java
+++ b/src/main/java/electroblob/wizardry/spell/FontOfMana.java
@@ -52,8 +52,8 @@ public class FontOfMana extends Spell {
double y = caster.getEntityBoundingBox().minY;
double z = caster.posZ + radius * Math.sin(angle);
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).lifetime(50)
- .colour(1, 1 - hue, 0.6f + hue).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).time(50)
+ .clr(1, 1 - hue, 0.6f + hue).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/ForestsCurse.java b/src/main/java/electroblob/wizardry/spell/ForestsCurse.java
index e08bd145..0cd51ef4 100644
--- a/src/main/java/electroblob/wizardry/spell/ForestsCurse.java
+++ b/src/main/java/electroblob/wizardry/spell/ForestsCurse.java
@@ -50,13 +50,13 @@ public class ForestsCurse extends SpellAreaEffect {
float brightness = world.rand.nextFloat() / 4;
ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).vel(0, -0.2, 0)
- .colour(0.05f + brightness, 0.2f + brightness, 0).spawn(world);
+ .clr(0.05f + brightness, 0.2f + brightness, 0).spawn(world);
brightness = world.rand.nextFloat() / 4;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.05, 0).lifetime(50)
- .colour(0.1f + brightness, 0.2f + brightness, 0).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.05, 0).time(50)
+ .clr(0.1f + brightness, 0.2f + brightness, 0).spawn(world);
- ParticleBuilder.create(Type.LEAF).pos(x, y, z).vel(0, -0.01, 0).lifetime(40 + world.rand.nextInt(12)).spawn(world);
+ ParticleBuilder.create(Type.LEAF).pos(x, y, z).vel(0, -0.01, 0).time(40 + world.rand.nextInt(12)).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/Freeze.java b/src/main/java/electroblob/wizardry/spell/Freeze.java
index 48f19bb0..3347b566 100644
--- a/src/main/java/electroblob/wizardry/spell/Freeze.java
+++ b/src/main/java/electroblob/wizardry/spell/Freeze.java
@@ -87,8 +87,8 @@ public class Freeze extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
float brightness = 0.5f + (world.rand.nextFloat() / 2);
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8))
- .colour(brightness, brightness + 0.1f, 1).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(12 + world.rand.nextInt(8))
+ .clr(brightness, brightness + 0.1f, 1).spawn(world);
ParticleBuilder.create(Type.SNOW).pos(x, y, z).spawn(world);
}
diff --git a/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java b/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java
index e2792eb9..19b8a8bc 100644
--- a/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java
+++ b/src/main/java/electroblob/wizardry/spell/FreezingWeapon.java
@@ -59,7 +59,7 @@ public class FreezingWeapon extends Spell {
double x = caster.posX + world.rand.nextDouble() * 2 - 1;
double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble();
double z = caster.posZ + world.rand.nextDouble() * 2 - 1;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.9f, 0.7f, 1).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(0.9f, 0.7f, 1).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/FrostRay.java b/src/main/java/electroblob/wizardry/spell/FrostRay.java
index 1a360880..47c36b37 100644
--- a/src/main/java/electroblob/wizardry/spell/FrostRay.java
+++ b/src/main/java/electroblob/wizardry/spell/FrostRay.java
@@ -104,9 +104,9 @@ public class FrostRay extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
float brightness = world.rand.nextFloat();
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).lifetime(8 + world.rand.nextInt(12))
- .colour(0.4f + 0.6f * brightness, 0.6f + 0.4f*brightness, 1).spawn(world);
- ParticleBuilder.create(Type.SNOW).pos(x, y, z).vel(vx, vy, vz).lifetime(8 + world.rand.nextInt(12)).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).time(8 + world.rand.nextInt(12))
+ .clr(0.4f + 0.6f * brightness, 0.6f + 0.4f*brightness, 1).spawn(world);
+ ParticleBuilder.create(Type.SNOW).pos(x, y, z).vel(vx, vy, vz).time(8 + world.rand.nextInt(12)).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/Glide.java b/src/main/java/electroblob/wizardry/spell/Glide.java
index 0db03cca..7821c800 100644
--- a/src/main/java/electroblob/wizardry/spell/Glide.java
+++ b/src/main/java/electroblob/wizardry/spell/Glide.java
@@ -35,11 +35,11 @@ public class Glide extends Spell {
double x = caster.posX - 0.25 + world.rand.nextDouble() / 2;
double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble();
double z = caster.posZ - 0.25 + world.rand.nextDouble() / 2;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).lifetime(15).colour(1, 1, 1).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).time(15).clr(1, 1, 1).spawn(world);
x = caster.posX - 0.25 + world.rand.nextDouble() / 2;
y = caster.getEntityBoundingBox().minY + world.rand.nextDouble();
z = caster.posZ - 0.25 + world.rand.nextDouble() / 2;
- ParticleBuilder.create(Type.LEAF).pos(x, y, z).lifetime(20).spawn(world);
+ ParticleBuilder.create(Type.LEAF).pos(x, y, z).time(20).spawn(world);
}
if(ticksInUse % 24 == 0){
diff --git a/src/main/java/electroblob/wizardry/spell/GroupHeal.java b/src/main/java/electroblob/wizardry/spell/GroupHeal.java
index 58030155..71593ec1 100644
--- a/src/main/java/electroblob/wizardry/spell/GroupHeal.java
+++ b/src/main/java/electroblob/wizardry/spell/GroupHeal.java
@@ -9,8 +9,8 @@ import electroblob.wizardry.constants.Tier;
import electroblob.wizardry.entity.living.ISummonedCreature;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardrySounds;
-import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.ParticleBuilder;
+import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
@@ -49,10 +49,10 @@ public class GroupHeal extends Spell {
double x = caster.posX + world.rand.nextDouble() * 2 - 1;
double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble();
double z = caster.posZ + world.rand.nextDouble() * 2 - 1;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(1, 1, 0.3f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(1, 1, 0.3f).spawn(world);
}
-
- Wizardry.proxy.spawnEntityParticle(world, caster, 15, 1, 1, 0.3f);
+
+ ParticleBuilder.create(Type.BUFF).entity(caster).clr(1, 1, 0.3f).spawn(world);
}
WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F,
@@ -78,10 +78,10 @@ public class GroupHeal extends Spell {
double x = caster.posX + world.rand.nextDouble() * 2 - 1;
double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble();
double z = caster.posZ + world.rand.nextDouble() * 2 - 1;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(1, 1, 0.3f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(1, 1, 0.3f).spawn(world);
}
-
- Wizardry.proxy.spawnEntityParticle(world, caster, 15, 1, 1, 0.3f);
+
+ ParticleBuilder.create(Type.BUFF).entity(caster).clr(1, 1, 0.3f).spawn(world);
}
WizardryUtilities.playSoundAtPlayer(caster, WizardrySounds.SPELL_HEAL, 0.7F,
diff --git a/src/main/java/electroblob/wizardry/spell/HealAlly.java b/src/main/java/electroblob/wizardry/spell/HealAlly.java
index f6ccdb65..e36ab8eb 100644
--- a/src/main/java/electroblob/wizardry/spell/HealAlly.java
+++ b/src/main/java/electroblob/wizardry/spell/HealAlly.java
@@ -41,10 +41,10 @@ public class HealAlly extends SpellRay {
double x1 = (double)((float)entity.posX + world.rand.nextFloat() * 2 - 1.0f);
double y1 = (double)((float)entity.getEntityBoundingBox().minY + entity.getEyeHeight() - 0.5f + world.rand.nextFloat());
double z1 = (double)((float)entity.posZ + world.rand.nextFloat() * 2 - 1.0f);
- ParticleBuilder.create(Type.SPARKLE).pos(x1, y1, z1).vel(0, 0.1F, 0).colour(r, g, b).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x1, y1, z1).vel(0, 0.1F, 0).clr(r, g, b).spawn(world);
}
-
- Wizardry.proxy.spawnEntityParticle(world, entity, 15, r, g, b);
+
+ ParticleBuilder.create(Type.BUFF).entity(caster).clr(r, g, b).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/IceStatue.java b/src/main/java/electroblob/wizardry/spell/IceStatue.java
index 2132ef16..9c5b1cfd 100644
--- a/src/main/java/electroblob/wizardry/spell/IceStatue.java
+++ b/src/main/java/electroblob/wizardry/spell/IceStatue.java
@@ -55,9 +55,9 @@ public class IceStatue extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
float brightness = 0.5f + world.rand.nextFloat() * 0.5f;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8))
- .colour(brightness, brightness + 0.1f, 1.0f).spawn(world);
- ParticleBuilder.create(Type.SNOW).pos(x, y, z).lifetime(20 + world.rand.nextInt(10)).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(12 + world.rand.nextInt(8))
+ .clr(brightness, brightness + 0.1f, 1.0f).spawn(world);
+ ParticleBuilder.create(Type.SNOW).pos(x, y, z).time(20 + world.rand.nextInt(10)).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java b/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java
index caf3f92e..ec1178fd 100644
--- a/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java
+++ b/src/main/java/electroblob/wizardry/spell/ImbueWeapon.java
@@ -68,7 +68,7 @@ public class ImbueWeapon extends Spell {
double x = caster.posX + world.rand.nextDouble() * 2 - 1;
double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble();
double z = caster.posZ + world.rand.nextDouble() * 2 - 1;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.9f, 0.7f, 1).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(0.9f, 0.7f, 1).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/Intimidate.java b/src/main/java/electroblob/wizardry/spell/Intimidate.java
index 2d8f6aa4..626c7210 100644
--- a/src/main/java/electroblob/wizardry/spell/Intimidate.java
+++ b/src/main/java/electroblob/wizardry/spell/Intimidate.java
@@ -68,7 +68,7 @@ public class Intimidate extends Spell {
double x = caster.posX - 1 + world.rand.nextDouble() * 2;
double y = caster.getEntityBoundingBox().minY + 1.5 + world.rand.nextDouble() * 0.5;
double z = caster.posZ - 1 + world.rand.nextDouble() * 2;
- ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.9f, 0.1f, 0).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.9f, 0.1f, 0).spawn(world);
}
}
WizardryUtilities.playSoundAtPlayer(caster, SoundEvents.ENTITY_ENDERDRAGON_GROWL, 1.0f, 1.0f);
diff --git a/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java b/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java
index 859a5a90..425e7c3b 100644
--- a/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java
+++ b/src/main/java/electroblob/wizardry/spell/InvigoratingPresence.java
@@ -53,7 +53,7 @@ public class InvigoratingPresence extends Spell {
double y = caster.getEntityBoundingBox().minY;
double z = caster.posZ + radius * Math.sin(angle);
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).lifetime(50).colour(1, 0.2f, 0.2f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.03, 0).time(50).clr(1, 0.2f, 0.2f).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/InvokeWeather.java b/src/main/java/electroblob/wizardry/spell/InvokeWeather.java
index e2773b79..71ce3368 100644
--- a/src/main/java/electroblob/wizardry/spell/InvokeWeather.java
+++ b/src/main/java/electroblob/wizardry/spell/InvokeWeather.java
@@ -54,7 +54,7 @@ public class InvokeWeather extends Spell {
double x = caster.posX + world.rand.nextDouble() * 2 - 1;
double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble();
double z = caster.posZ + world.rand.nextDouble() * 2 - 1;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.5f, 0.7f, 1).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(0.5f, 0.7f, 1).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/Levitation.java b/src/main/java/electroblob/wizardry/spell/Levitation.java
index 34779ce6..60e16ab8 100644
--- a/src/main/java/electroblob/wizardry/spell/Levitation.java
+++ b/src/main/java/electroblob/wizardry/spell/Levitation.java
@@ -30,7 +30,7 @@ public class Levitation extends Spell {
double x = caster.posX - 0.25 + world.rand.nextDouble() * 0.5;
double y = caster.getEntityBoundingBox().minY;
double z = caster.posZ - 0.25 + world.rand.nextDouble() * 0.5;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).lifetime(15).colour(0.5f, 1, 0.7f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, -0.1, 0).time(15).clr(0.5f, 1, 0.7f).spawn(world);
}
if(ticksInUse % 24 == 0 && world.isRemote){
Wizardry.proxy.playMovingSound(caster, WizardrySounds.SPELL_LOOP_SPARKLE, 0.5f, 1, false);
diff --git a/src/main/java/electroblob/wizardry/spell/LifeDrain.java b/src/main/java/electroblob/wizardry/spell/LifeDrain.java
index 364b5890..b60109f9 100644
--- a/src/main/java/electroblob/wizardry/spell/LifeDrain.java
+++ b/src/main/java/electroblob/wizardry/spell/LifeDrain.java
@@ -89,10 +89,10 @@ public class LifeDrain extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
- if(world.rand.nextInt(5) == 0) ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.1f, 0, 0).spawn(world);
+ if(world.rand.nextInt(5) == 0) ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.1f, 0, 0).spawn(world);
// This used to multiply the velocity by the distance from the caster
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).lifetime(8 + world.rand.nextInt(6))
- .colour(0.5f, 0, 0).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).time(8 + world.rand.nextInt(6))
+ .clr(0.5f, 0, 0).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/LightningPulse.java b/src/main/java/electroblob/wizardry/spell/LightningPulse.java
index acd809d4..69c1543b 100644
--- a/src/main/java/electroblob/wizardry/spell/LightningPulse.java
+++ b/src/main/java/electroblob/wizardry/spell/LightningPulse.java
@@ -5,11 +5,12 @@ import java.util.List;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.constants.SpellType;
import electroblob.wizardry.constants.Tier;
-import electroblob.wizardry.entity.construct.EntityLightningPulse;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
+import electroblob.wizardry.util.ParticleBuilder;
+import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLivingBase;
@@ -72,14 +73,10 @@ public class LightningPulse extends Spell {
}
}
- if(!world.isRemote){
- // Surely neither of the commented lines would have done anything?
- EntityLightningPulse lightningpulse = new EntityLightningPulse(world);
- lightningpulse.setPosition(caster.posX, caster.getEntityBoundingBox().minY, caster.posZ);
- //lightningpulse.setCaster(caster);
- lightningpulse.lifetime = 7;
- //lightningpulse.damageMultiplier = modifiers.get(SpellModifiers.POTENCY);
- world.spawnEntity(lightningpulse);
+ if(world.isRemote){
+ ParticleBuilder.create(Type.LIGHTNING_PULSE).pos(caster.posX, caster.getEntityBoundingBox().minY
+ + WizardryUtilities.ANTI_Z_FIGHTING_OFFSET, caster.posZ)
+ .scale(modifiers.get(WizardryItems.blast_upgrade)).spawn(world);
}
caster.swingArm(hand);
diff --git a/src/main/java/electroblob/wizardry/spell/LightningRay.java b/src/main/java/electroblob/wizardry/spell/LightningRay.java
index de680000..3521b3d5 100644
--- a/src/main/java/electroblob/wizardry/spell/LightningRay.java
+++ b/src/main/java/electroblob/wizardry/spell/LightningRay.java
@@ -3,7 +3,6 @@ package electroblob.wizardry.spell;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.constants.SpellType;
import electroblob.wizardry.constants.Tier;
-import electroblob.wizardry.entity.EntityArc;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
@@ -18,6 +17,7 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.World;
@@ -71,23 +71,18 @@ public class LightningRay extends SpellRay {
BASE_DAMAGE * modifiers.get(SpellModifiers.POTENCY));
}
- if(!world.isRemote){
+ if(world.isRemote){
+
+ if(ticksInUse % 3 == 0) ParticleBuilder.create(Type.LIGHTNING).entity(caster)
+ .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(target).spawn(world);
- if(ticksInUse % 2 == 0){
-
- EntityArc arc = new EntityArc(world);
- arc.setEndpointCoords(caster.posX, caster.posY + 1.2, caster.posZ, target.posX,
- target.posY + target.height / 2, target.posZ);
- arc.lifetime = 1;
- world.spawnEntity(arc);
- }
-
- }else{
// Particle effect
for(int i=0; i<5; i++){
ParticleBuilder.create(Type.SPARK, target).spawn(world);
}
}
+
+ return true;
}
return false;
@@ -101,21 +96,15 @@ public class LightningRay extends SpellRay {
@Override
protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){
// This is a nice example of when onMiss is used for more than just returning a boolean
- if(!world.isRemote){
+ if(world.isRemote && ticksInUse % 4 == 0){
- if(ticksInUse % 2 == 0){
-
- double freeRange = 0.8 * baseRange; // The arc does not reach full range when it has a free end
-
- EntityArc arc = new EntityArc(world);
- arc.setEndpointCoords(caster.posX, caster.posY + 1.2, caster.posZ,
- caster.posX + caster.getLookVec().x * freeRange,
- caster.posY + caster.getEyeHeight() + caster.getLookVec().y * freeRange,
- caster.posZ + caster.getLookVec().z * freeRange);
- arc.lifetime = 1;
- world.spawnEntity(arc);
-
- }
+ if(caster != null) origin = origin.subtract(0, Y_OFFSET, 0);
+
+ double freeRange = 0.8 * baseRange; // The arc does not reach full range when it has a free end
+ Vec3d endpoint = origin.add(direction.scale(freeRange));
+
+ ParticleBuilder.create(Type.LIGHTNING).entity(caster)
+ .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(endpoint).spawn(world);
}
return true;
diff --git a/src/main/java/electroblob/wizardry/spell/LightningWeb.java b/src/main/java/electroblob/wizardry/spell/LightningWeb.java
index 72b2cc67..8f5f1256 100644
--- a/src/main/java/electroblob/wizardry/spell/LightningWeb.java
+++ b/src/main/java/electroblob/wizardry/spell/LightningWeb.java
@@ -5,7 +5,6 @@ import java.util.List;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.constants.SpellType;
import electroblob.wizardry.constants.Tier;
-import electroblob.wizardry.entity.EntityArc;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
@@ -20,6 +19,7 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.World;
@@ -119,19 +119,20 @@ public class LightningWeb extends SpellRay {
@Override
protected boolean onMiss(World world, EntityLivingBase caster, int ticksInUse, SpellModifiers modifiers){
// This is a nice example of when onMiss is used for more than just returning a boolean
- if(!world.isRemote){
+ if(world.isRemote){
+
+ if(caster != null) origin = origin.subtract(0, Y_OFFSET, 0);
+
+ double freeRange = 0.8 * baseRange; // The arc does not reach full range when it has a free end
+ Vec3d endpoint = origin.add(direction.scale(freeRange));
+
+ ParticleBuilder.create(Type.BEAM).entity(caster).clr(0.2f, 0.6f, 1)
+ .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(endpoint).spawn(world);
if(ticksInUse % 2 == 0){
-
- double freeRange = 0.8 * baseRange; // The arc does not reach full range when it has a free end
- EntityArc arc = new EntityArc(world);
- arc.setEndpointCoords(caster.posX, caster.posY + 1.2, caster.posZ,
- caster.posX + caster.getLookVec().x * freeRange,
- caster.posY + caster.getEyeHeight() + caster.getLookVec().y * freeRange,
- caster.posZ + caster.getLookVec().z * freeRange);
- arc.lifetime = 1;
- world.spawnEntity(arc);
+ ParticleBuilder.create(Type.LIGHTNING).entity(caster)
+ .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(endpoint).spawn(world);
}
}
@@ -150,17 +151,16 @@ public class LightningWeb extends SpellRay {
MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK), damage);
}
- if(!world.isRemote){
- // Arc entity spawning
- if(ticksInUse % 2 == 0){
- EntityArc arc = new EntityArc(world);
- arc.setEndpointCoords(origin.posX, origin.posY + 1.2, origin.posZ, target.posX,
- target.posY + target.height / 2, target.posZ);
- arc.lifetime = 1;
- world.spawnEntity(arc);
- }
+ if(world.isRemote){
- }else{
+ ParticleBuilder.create(Type.BEAM).entity(caster).clr(0.2f, 0.6f, 1)
+ .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(target).spawn(world);
+
+ if(ticksInUse % 3 == 0){
+ ParticleBuilder.create(Type.LIGHTNING).entity(caster)
+ .pos(caster != null ? origin.subtract(caster.getPositionVector()) : origin).target(target).spawn(world);
+ }
+
// Particle effect
for(int i=0; i<5; i++){
ParticleBuilder.create(Type.SPARK, target).spawn(world);
diff --git a/src/main/java/electroblob/wizardry/spell/Metamorphosis.java b/src/main/java/electroblob/wizardry/spell/Metamorphosis.java
index 56ec9107..174e28ef 100644
--- a/src/main/java/electroblob/wizardry/spell/Metamorphosis.java
+++ b/src/main/java/electroblob/wizardry/spell/Metamorphosis.java
@@ -34,6 +34,7 @@ import net.minecraft.entity.passive.EntityPig;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class Metamorphosis extends SpellRay {
@@ -111,7 +112,7 @@ public class Metamorphosis extends SpellRay {
}else{
for(int i=0; i<5; i++){
- ParticleBuilder.create(Type.DARK_MAGIC).pos(xPos, yPos, zPos).colour(0.1f, 0, 0).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC).pos(xPos, yPos, zPos).clr(0.1f, 0, 0).spawn(world);
}
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/MindControl.java b/src/main/java/electroblob/wizardry/spell/MindControl.java
index 96c4cccd..0c10155b 100644
--- a/src/main/java/electroblob/wizardry/spell/MindControl.java
+++ b/src/main/java/electroblob/wizardry/spell/MindControl.java
@@ -76,10 +76,10 @@ public class MindControl extends SpellRay {
for(int i=0; i<10; i++){
ParticleBuilder.create(Type.DARK_MAGIC, world.rand, target.posX,
target.getEntityBoundingBox().minY + target.getEyeHeight(), target.posZ, 0.25, false)
- .colour(0.8f, 0.2f, 1.0f).spawn(world);
+ .clr(0.8f, 0.2f, 1.0f).spawn(world);
ParticleBuilder.create(Type.DARK_MAGIC, world.rand, target.posX,
target.getEntityBoundingBox().minY + target.getEyeHeight(), target.posZ, 0.25, false)
- .colour(0.2f, 0.04f, 0.25f).spawn(world);
+ .clr(0.2f, 0.04f, 0.25f).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/MindTrick.java b/src/main/java/electroblob/wizardry/spell/MindTrick.java
index 0bf6b2fa..739d585f 100644
--- a/src/main/java/electroblob/wizardry/spell/MindTrick.java
+++ b/src/main/java/electroblob/wizardry/spell/MindTrick.java
@@ -57,7 +57,7 @@ public class MindTrick extends SpellRay {
for(int i=0; i<10; i++){
ParticleBuilder.create(Type.DARK_MAGIC, world.rand, target.posX,
target.getEntityBoundingBox().minY + target.getEyeHeight(), target.posZ, 0.25, false)
- .colour(0.8f, 0.2f, 1.0f).spawn(world);
+ .clr(0.8f, 0.2f, 1.0f).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/Petrify.java b/src/main/java/electroblob/wizardry/spell/Petrify.java
index bdbaba16..757d9f29 100644
--- a/src/main/java/electroblob/wizardry/spell/Petrify.java
+++ b/src/main/java/electroblob/wizardry/spell/Petrify.java
@@ -53,8 +53,8 @@ public class Petrify extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)).colour(0.2f, 0.2f, 0.2f).spawn(world);
- ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.1f, 0.1f, 0.1f).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(12 + world.rand.nextInt(8)).clr(0.2f, 0.2f, 0.2f).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.1f, 0.1f, 0.1f).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java b/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java
index f9f87a10..e1d71f41 100644
--- a/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java
+++ b/src/main/java/electroblob/wizardry/spell/PlagueOfDarkness.java
@@ -58,12 +58,12 @@ public class PlagueOfDarkness extends Spell {
particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
ParticleBuilder.create(Type.DARK_MAGIC).pos(particleX, caster.getEntityBoundingBox().minY, particleZ)
- .vel(particleX - caster.posX, 0, particleZ - caster.posZ).colour(0.1f, 0, 0).spawn(world);
+ .vel(particleX - caster.posX, 0, particleZ - caster.posZ).clr(0.1f, 0, 0).spawn(world);
particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ)
- .vel(particleX - caster.posX, 0, particleZ - caster.posZ).lifetime(30).colour(0.1f, 0, 0.05f).spawn(world);
+ .vel(particleX - caster.posX, 0, particleZ - caster.posZ).time(30).clr(0.1f, 0, 0.05f).spawn(world);
particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
diff --git a/src/main/java/electroblob/wizardry/spell/Poison.java b/src/main/java/electroblob/wizardry/spell/Poison.java
index 0a81900e..057f0f2c 100644
--- a/src/main/java/electroblob/wizardry/spell/Poison.java
+++ b/src/main/java/electroblob/wizardry/spell/Poison.java
@@ -68,8 +68,8 @@ public class Poison extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
- ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.3f, 0.7f, 0).spawn(world);
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)).colour(0.1f, 0.4f, 0).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.3f, 0.7f, 0).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(12 + world.rand.nextInt(8)).clr(0.1f, 0.4f, 0).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/Shockwave.java b/src/main/java/electroblob/wizardry/spell/Shockwave.java
index 52bf90a8..5b970204 100644
--- a/src/main/java/electroblob/wizardry/spell/Shockwave.java
+++ b/src/main/java/electroblob/wizardry/spell/Shockwave.java
@@ -78,12 +78,12 @@ public class Shockwave extends Spell {
particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ)
- .vel(particleX - caster.posX, 0, particleZ - caster.posZ).lifetime(30).colour(0.8f, 0.8f, 1).spawn(world);
+ .vel(particleX - caster.posX, 0, particleZ - caster.posZ).time(30).clr(0.8f, 0.8f, 1).spawn(world);
particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
ParticleBuilder.create(Type.SPARKLE).pos(particleX, caster.getEntityBoundingBox().minY, particleZ)
- .vel(particleX - caster.posX, 0, particleZ - caster.posZ).lifetime(30).colour(0.9f, 0.9f, 0.9f).spawn(world);
+ .vel(particleX - caster.posX, 0, particleZ - caster.posZ).time(30).clr(0.9f, 0.9f, 0.9f).spawn(world);
particleX = caster.posX - 1.0d + 2 * world.rand.nextDouble();
particleZ = caster.posZ - 1.0d + 2 * world.rand.nextDouble();
diff --git a/src/main/java/electroblob/wizardry/spell/Slime.java b/src/main/java/electroblob/wizardry/spell/Slime.java
index 4b04b83d..b972686b 100644
--- a/src/main/java/electroblob/wizardry/spell/Slime.java
+++ b/src/main/java/electroblob/wizardry/spell/Slime.java
@@ -87,7 +87,7 @@ public class Slime extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
world.spawnParticle(EnumParticleTypes.SLIME, x, y, z, 0, 0, 0);
- ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.2f, 0.8f, 0.1f).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.2f, 0.8f, 0.1f).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/Snare.java b/src/main/java/electroblob/wizardry/spell/Snare.java
index d7e64753..fa2259ea 100644
--- a/src/main/java/electroblob/wizardry/spell/Snare.java
+++ b/src/main/java/electroblob/wizardry/spell/Snare.java
@@ -54,9 +54,9 @@ public class Snare extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
float brightness = world.rand.nextFloat() * 0.25f;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(20 + world.rand.nextInt(8))
- .colour(brightness, brightness + 0.1f, 0).spawn(world);
- ParticleBuilder.create(Type.LEAF).pos(x, y, z).vel(0, -0.01, 0).lifetime(40 + world.rand.nextInt(10)).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(20 + world.rand.nextInt(8))
+ .clr(brightness, brightness + 0.1f, 0).spawn(world);
+ ParticleBuilder.create(Type.LEAF).pos(x, y, z).vel(0, -0.01, 0).time(40 + world.rand.nextInt(10)).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/SpellBuff.java b/src/main/java/electroblob/wizardry/spell/SpellBuff.java
index 0c91c08f..f4277c69 100644
--- a/src/main/java/electroblob/wizardry/spell/SpellBuff.java
+++ b/src/main/java/electroblob/wizardry/spell/SpellBuff.java
@@ -144,10 +144,10 @@ public class SpellBuff extends Spell {
double x = caster.posX + world.rand.nextDouble() * 2 - 1;
double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble();
double z = caster.posZ + world.rand.nextDouble() * 2 - 1;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(r, g, b).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(r, g, b).spawn(world);
}
- Wizardry.proxy.spawnEntityParticle(world, caster, 15, r, g, b);
+ ParticleBuilder.create(Type.BUFF).entity(caster).clr(r, g, b).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/SpellConjuration.java b/src/main/java/electroblob/wizardry/spell/SpellConjuration.java
index 9dd9d068..c339932a 100644
--- a/src/main/java/electroblob/wizardry/spell/SpellConjuration.java
+++ b/src/main/java/electroblob/wizardry/spell/SpellConjuration.java
@@ -94,7 +94,7 @@ public class SpellConjuration extends Spell {
double x = caster.posX + world.rand.nextDouble() * 2 - 1;
double y = caster.getEntityBoundingBox().minY + caster.getEyeHeight() - 0.5 + world.rand.nextDouble();
double z = caster.posZ + world.rand.nextDouble() * 2 - 1;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.7f, 0.9f, 1).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(0.7f, 0.9f, 1).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java b/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java
index 1fee0dab..5166d9ba 100644
--- a/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java
+++ b/src/main/java/electroblob/wizardry/spell/SummonIronGolem.java
@@ -39,7 +39,7 @@ public class SummonIronGolem extends Spell {
double x = pos.getX() + world.rand.nextDouble() * 2 - 1;
double y = pos.getY() + 0.5 + world.rand.nextDouble();
double z = pos.getZ() + world.rand.nextDouble() * 2 - 1;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).colour(0.6f, 0.6f, 1).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).clr(0.6f, 0.6f, 1).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java b/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java
index e168d3b8..3be56349 100644
--- a/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java
+++ b/src/main/java/electroblob/wizardry/spell/SummonSnowGolem.java
@@ -39,7 +39,7 @@ public class SummonSnowGolem extends Spell {
double x = pos.getX() + world.rand.nextDouble() * 2 - 1;
double y = pos.getY() + 0.5 + world.rand.nextDouble();
double z = pos.getZ() + world.rand.nextDouble() * 2 - 1;
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).colour(0.6f, 0.6f, 1).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(0, 0.1, 0).clr(0.6f, 0.6f, 1).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/Thunderstorm.java b/src/main/java/electroblob/wizardry/spell/Thunderstorm.java
index a96d65ea..06ca648b 100644
--- a/src/main/java/electroblob/wizardry/spell/Thunderstorm.java
+++ b/src/main/java/electroblob/wizardry/spell/Thunderstorm.java
@@ -5,12 +5,12 @@ import java.util.List;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.constants.SpellType;
import electroblob.wizardry.constants.Tier;
-import electroblob.wizardry.entity.EntityArc;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.ParticleBuilder;
+import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLiving;
@@ -72,12 +72,10 @@ public class Thunderstorm extends Spell {
if(WizardryUtilities.isValidTarget(caster, secondaryTarget)){
- if(!world.isRemote){
- EntityArc arc = new EntityArc(world);
- arc.setEndpointCoords(x, y + 1, z, secondaryTarget.posX,
- secondaryTarget.posY + secondaryTarget.height / 2, secondaryTarget.posZ);
- world.spawnEntity(arc);
- }else{
+ if(world.isRemote){
+
+ ParticleBuilder.create(Type.LIGHTNING).pos(x, y, z).target(secondaryTarget).spawn(world);
+
ParticleBuilder.spawnShockParticles(world, secondaryTarget.posX,
secondaryTarget.getEntityBoundingBox().minY + secondaryTarget.height / 2,
secondaryTarget.posZ);
@@ -102,14 +100,9 @@ public class Thunderstorm extends Spell {
if(!secondaryTargets.contains(tertiaryTarget)
&& WizardryUtilities.isValidTarget(caster, tertiaryTarget)){
- if(!world.isRemote){
- EntityArc arc = new EntityArc(world);
- arc.setEndpointCoords(secondaryTarget.posX,
- secondaryTarget.posY + secondaryTarget.height / 2, secondaryTarget.posZ,
- tertiaryTarget.posX, tertiaryTarget.posY + tertiaryTarget.height / 2,
- tertiaryTarget.posZ);
- world.spawnEntity(arc);
- }else{
+ if(world.isRemote){
+ ParticleBuilder.create(Type.LIGHTNING).entity(secondaryTarget)
+ .pos(0, secondaryTarget.height/2, 0).target(tertiaryTarget).spawn(world);
ParticleBuilder.spawnShockParticles(world, tertiaryTarget.posX,
tertiaryTarget.getEntityBoundingBox().minY + tertiaryTarget.height / 2,
tertiaryTarget.posZ);
diff --git a/src/main/java/electroblob/wizardry/spell/WallOfFrost.java b/src/main/java/electroblob/wizardry/spell/WallOfFrost.java
index 37a55b55..1ab2670d 100644
--- a/src/main/java/electroblob/wizardry/spell/WallOfFrost.java
+++ b/src/main/java/electroblob/wizardry/spell/WallOfFrost.java
@@ -129,9 +129,9 @@ public class WallOfFrost extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
float brightness = world.rand.nextFloat();
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).lifetime(8 + world.rand.nextInt(12))
- .colour(0.4f + 0.6f * brightness, 0.6f + 0.4f*brightness, 1).spawn(world);
- ParticleBuilder.create(Type.SNOW).pos(x, y, z).vel(vx, vy, vz).lifetime(8 + world.rand.nextInt(12)).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).time(8 + world.rand.nextInt(12))
+ .clr(0.4f + 0.6f * brightness, 0.6f + 0.4f*brightness, 1).spawn(world);
+ ParticleBuilder.create(Type.SNOW).pos(x, y, z).vel(vx, vy, vz).time(8 + world.rand.nextInt(12)).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/spell/Wither.java b/src/main/java/electroblob/wizardry/spell/Wither.java
index 3cacf432..54d260fb 100644
--- a/src/main/java/electroblob/wizardry/spell/Wither.java
+++ b/src/main/java/electroblob/wizardry/spell/Wither.java
@@ -64,8 +64,8 @@ public class Wither extends SpellRay {
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
- ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).colour(0.1f, 0, 0).spawn(world);
- ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).lifetime(12 + world.rand.nextInt(8)).colour(0.1f, 0, 0.05f).spawn(world);
+ ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.1f, 0, 0).spawn(world);
+ ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).time(12 + world.rand.nextInt(8)).clr(0.1f, 0, 0.05f).spawn(world);
}
}
diff --git a/src/main/java/electroblob/wizardry/util/ParticleBuilder.java b/src/main/java/electroblob/wizardry/util/ParticleBuilder.java
index 839dc831..eb78c50b 100644
--- a/src/main/java/electroblob/wizardry/util/ParticleBuilder.java
+++ b/src/main/java/electroblob/wizardry/util/ParticleBuilder.java
@@ -4,6 +4,7 @@ import java.util.Random;
import electroblob.wizardry.Wizardry;
import net.minecraft.entity.Entity;
+import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
@@ -13,17 +14,14 @@ import net.minecraft.world.World;
* "Don't waste time spawning particles manually - let {@code ParticleBuilder} do the work for you!"
*
* Singleton class that builds wizardry particles. This is an alternative (and neater, I think) solution to using varargs.
- * All building methods are chainable, so particles can be created using only one line of code (This is similar to the
- * BufferBuilder system). The number of different combinations of parameters now required for the various particle
+ * All building methods are chainable, so particles can be created using only one line of code, similar to the
+ * {@code BufferBuilder} system. The number of different combinations of parameters now required for the various particle
* types in wizardry made the method overloads in the proxies very cumbersome and inevitably resulted in redundant
* parameters, which made the code messy and hard to read. Those methods have now been removed.
*
- * It also goes without saying that this class should only ever be used client-side. Attempting to spawn particles
- * on the server side will not work and will print a warning to the console.
- *
* {@link ParticleBuilder#instance} retrieves the static instance of the particle builder. Use
* {@link ParticleBuilder#particle(Type)} to start building a particle, or alternatively use the static
- * convenience version {@link ParticleBuilder#create(Type)}. Use {@link ParticleBuilder#spawn()}
+ * convenience version {@link ParticleBuilder#create(Type)}. Use {@link ParticleBuilder#spawn(World)}
* to finish building and spawn the particle. Between these two, a variety of parameters can be set using the various
* setter methods (see individual method descriptions for more details). These, along with {@code ParticleBuilder.particle(...)},
* return the particle builder instance, allowing them to be chained together to spawn particles using a single line of code.
@@ -32,10 +30,16 @@ import net.minecraft.world.World;
*
* For example, a typical call to the particle builder might look something like this:
*
- * ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).colour(r, g, b).spawn(world);
+ * ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).clr(r, g, b).spawn(world);
+ *
+ * It also goes without saying that this class should only ever be used client-side. Attempting to spawn particles
+ * on the server side will not work and will print a warning to the console.
* @author Electroblob
* @since Wizardry 4.2
*/
+/* This isn't strictly a builder class in the traditional sense, because rather than returning the built object at the
+ * end, it sends it to be processed instead and returns nothing. It's also lazy, see the comment about builder variables
+ * below. */
public final class ParticleBuilder {
/** The static instance of the particle builder. */
@@ -53,11 +57,16 @@ public final class ParticleBuilder {
private float r, g, b;
private float fr, fg, fb;
private double radius;
+ private double rpt;
private int lifetime;
private boolean gravity;
private boolean shaded;
+ private boolean collide;
private float scale;
private Entity entity;
+ private float yaw, pitch;
+ private double tx, ty, tz;
+ private Entity target;
/** Enum constants representing the different types of particle added by wizardry. As of 4.2.0, this has been moved
* from its own file {@code WizardryParticleType} to inside {@link ParticleBuilder}. This allowed its name to be
@@ -67,33 +76,33 @@ public final class ParticleBuilder {
*
* Individual constants have comments detailing their corresponding default parameters. A range of values indicates
* randomness. */
- public static enum Type {
- @Deprecated BLIZZARD,
+ public enum Type {
+ /** 3D-rendered light-beam particle.
Defaults:
Lifetime: 1 tick
Colour: white */ BEAM,
+ /** Helical animated 'buffing' particle.
Defaults:
Lifetime: 15 ticks
+ *
Velocity: (0, 0.27, 0)
Colour: white */ BUFF,
/** Spiral particle, like potions.
Defaults:
Lifetime: 8-40 ticks
Colour: white */ DARK_MAGIC,
/** Single pixel particle.
Defaults:
Lifetime: 16-80 ticks
Colour: white */ DUST,
- /** Rapid flash, like fireworks.
Defaults:
Lifetime: 4 ticks
Colour: white */ FLASH,
+ /** Rapid flash, like fireworks.
Defaults:
Lifetime: 6 ticks
Colour: white */ FLASH,
/** Small shard of ice.
Defaults:
Lifetime: 8-40 ticks
Gravity: true */ ICE,
/** Single leaf.
Defaults:
Lifetime: 10-15 ticks
Velocity: (0, -0.03, 0)
*
Colour: green/brown */ LEAF,
+ /** 3D-rendered lightning particle.
Defaults:
Lifetime: 3 ticks
Colour: blue */ LIGHTNING,
+ /** 2D lightning effect, normally on the ground.
Defaults:
Lifetime: 7 ticks
+ *
Facing: up */ LIGHTNING_PULSE,
/** Bubble that doesn't burst in air.
Defaults:
Lifetime: 8-40 ticks */ MAGIC_BUBBLE,
/** Scaleable, moving flame.
Defaults:
Lifetime: 8-40 ticks
*/ MAGIC_FIRE,
/** Soft-edged round particle.
Defaults:
Lifetime: 8-40 ticks
Colour: white */ PATH,
+ /** Scorch mark.
Defaults:
Lifetime: 100-140 ticks
Colour: black
Fade: black */ SCORCH,
/** Snowflake particle.
Defaults:
Lifetime: 40-50 ticks
Velocity: (0, -0.02, 0) */ SNOW,
/** Animated lightning particle.
Defaults:
Lifetime: 3 ticks */ SPARK,
- /** Animated sparkle particle.
Defaults:
Lifetime: 48-60 ticks
Colour: white */ SPARKLE,
- @Deprecated SPARKLE_ROTATING
+ /** Animated sparkle particle.
Defaults:
Lifetime: 48-60 ticks
Colour: white */ SPARKLE
}
private ParticleBuilder(){
reset();
}
- // Convenience methods
-
- // These may seem to go against the whole point of this class, but of course they return the ParticleBuilder instance
- // so anything else can still be chained onto them - centralising commonly-used particle spawning patterns without
- // losing any of the flexibility of the particle builder. In addition, callers of these methods are still free to
- // change any of the parameters that were set within them afterwards.
+ // ============================================= Core builder methods =============================================
/**
* Starts building a particle of the given type. Static convenience version of
@@ -106,11 +115,406 @@ public final class ParticleBuilder {
return ParticleBuilder.instance.particle(type);
}
+ /**
+ * Starts building a particle of the given type.
+ * @param type The type of particle to build
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is already building.
+ */
+ public ParticleBuilder particle(Type type){
+ if(building) throw new IllegalStateException("Already Building! Particle being built: " + getCurrentParticleString());
+ this.type = type;
+ this.building = true;
+ return this;
+ }
+
+ /** Gets a readable string representation of the current builder parameters; used in error messages. */
+ private String getCurrentParticleString(){
+ return String.format("[ Type: %s, Position: (%s, %s, %s), Velocity: (%s, %s, %s), Colour: (%s, %s, %s), "
+ + "Fade Colour: (%s, %s, %s), Radius: %s, Revs/tick: %s, Lifetime: %s, Gravity: %s, Shaded: %s,"
+ + "Scale: %s, Entity: %s ]",
+ type, x, y, z, vx, vy, vz, r, g, b, fr, fg, fb, radius, rpt, lifetime, gravity, shaded, scale, entity);
+ }
+
+ /**
+ * Sets the position of the particle being built. If unspecified, this defaults to the origin (0, 0, 0). If an entity
+ * is specified using {@link ParticleBuilder#entity(Entity)}, this will be relative to that entity's position.
+ *
+ * Affects: All particle types
+ * @param x The x coordinate to set
+ * @param y The y coordinate to set
+ * @param z The z coordinate to set
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder pos(double x, double y, double z){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ return this;
+ }
+
+ /**
+ * Sets the position of the particle being built. This is a vector-based alternative to {@link ParticleBuilder#pos(
+ * double, double, double)}, allowing for even more concise code when a vector is available.
+ *
+ * Affects: All particle types
+ * @param pos A vector representing the coordinates of the particle to be built.
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder pos(Vec3d pos){
+ return pos(pos.x, pos.y, pos.z);
+ }
+
+ /**
+ * Sets the velocity of the particle being built. If unspecified, this defaults to the particle's default velocity,
+ * specified within its constructor.
+ *
+ * Affects: All particle types except {@link Type#DUST DUST}
+ * @param vx The x velocity to set
+ * @param vy The y velocity to set
+ * @param vz The z velocity to set
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder vel(double vx, double vy, double vz){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.vx = vx;
+ this.vy = vy;
+ this.vz = vz;
+ return this;
+ }
+
+ /**
+ * Sets the velocity of the particle being built. This is a vector-based alternative to {@link ParticleBuilder#vel(
+ * double, double, double)}, allowing for even more concise code when a vector is available.
+ *
+ * Affects: All particle types
+ * @param vel A vector representing the velocity of the particle to be built.
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder vel(Vec3d vel){
+ return vel(vel.x, vel.y, vel.z);
+ }
+
+ /**
+ * Sets the colour of the particle being built. If unspecified, this defaults to the particle's default colour,
+ * specified within its constructor.
+ *
+ * Affects: {@link Type#DARK_MAGIC DARK_MAGIC}, {@link Type#DUST DUST}, {@link Type#FLASH FLASH},
+ * {@link Type#LEAF LEAF}, {@link Type#PATH PATH}, {@link Type#SPARKLE SPARKLE}
+ * @param r The red colour component to set; will be clamped to between 0 and 1
+ * @param g The green colour component to set; will be clamped to between 0 and 1
+ * @param b The blue colour component to set; will be clamped to between 0 and 1
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder clr(float r, float g, float b){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.r = MathHelper.clamp(r, 0, 1);
+ this.g = MathHelper.clamp(g, 0, 1);
+ this.b = MathHelper.clamp(b, 0, 1);
+ return this;
+ }
+
+ /**
+ * Sets the fade colour of the particle being built. If unspecified, this defaults to the whatever the particle's base
+ * colour is.
+ *
+ * Affects: {@link Type#DARK_MAGIC DARK_MAGIC}, {@link Type#DUST DUST}, {@link Type#FLASH FLASH},
+ * {@link Type#LEAF LEAF}, {@link Type#PATH PATH}, {@link Type#SPARKLE SPARKLE}
+ * @param r The red colour component to set; will be clamped to between 0 and 1
+ * @param g The green colour component to set; will be clamped to between 0 and 1
+ * @param b The blue colour component to set; will be clamped to between 0 and 1
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder fade(float r, float g, float b){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.fr = MathHelper.clamp(r, 0, 1);
+ this.fg = MathHelper.clamp(g, 0, 1);
+ this.fb = MathHelper.clamp(b, 0, 1);
+ return this;
+ }
+
+ /**
+ * Sets the scale of the particle being built. If unspecified, this defaults to 1.
+ *
+ * Affects: All particle types
+ * @param scale The scale to set, as a multiple of the particle's default scale
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder scale(float scale){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.scale = scale;
+ return this;
+ }
+
+ /**
+ * Sets the lifetime of the particle being built. If unspecified, this defaults to the particle's default lifetime,
+ * specified within its constructor.
+ *
+ * Affects: All particle types
+ * @param lifetime The lifetime to set in ticks
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder time(int lifetime){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.lifetime = lifetime;
+ return this;
+ }
+
+ /**
+ * Sets the spin parameters of the particle being built. If unspecified, these both default to 0.
+ *
+ * Affects: All particle types
+ * @param radius The rotation radius to set
+ * @param speed The rotation speed to set, in revolutions per tick
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder spin(double radius, double speed){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.radius = radius;
+ this.rpt = speed;
+ return this;
+ }
+
+ /**
+ * Sets the gravity of the particle being built. If unspecified, this defaults to false.
+ *
+ * Affects: {@link Type#ICE ICE}, {@link Type#SPARKLE SPARKLE}
+ * @param gravity True to enable gravity for the particle, false to disable
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder gravity(boolean gravity){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.gravity = gravity;
+ return this;
+ }
+
+ /**
+ * Sets the shading of the particle being built. If unspecified, this defaults to false.
+ *
+ * Affects: All particle types
+ * @param shaded True to enable shading for the particle, false for full brightness
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder shaded(boolean shaded){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.shaded = shaded;
+ return this;
+ }
+
+ /**
+ * Sets the collisions of the particle being built. If unspecified, this defaults to false.
+ *
+ * Affects: All particle types
+ * @param collide True to enable block collisions for the particle, false to disable
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder collide(boolean collide){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.collide = collide;
+ return this;
+ }
+
+ /**
+ * Sets the entity of the particle being built. This will cause the particle to move with the given entity, and will
+ * make the position specified using {@link ParticleBuilder#pos(double, double, double)} relative to that
+ * entity's position.
+ *
+ * Affects: All particle types
+ * @param entity The entity to set (passing in null will do nothing but will not cause any problems, so for the sake
+ * of conciseness it is not necessary to perform a null check on the passed-in argument)
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder entity(Entity entity){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.entity = entity;
+ return this;
+ }
+
+ /**
+ * Sets the rotation of the particle being built. If unspecified, the particle will use the default behaviour and
+ * rotate to face the viewer.
+ *
+ * Affects: All particle types
+ * @param yaw The yaw angle to set in degrees, where 0 is south.
+ * @param pitch The pitch angle to set in degrees, where 0 is horizontal.
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder face(float yaw, float pitch){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.yaw = yaw;
+ this.pitch = pitch;
+ return this;
+ }
+
+ /**
+ * Sets the rotation of the particle being built. This is an {@code EnumFacing}-based alternative to {@link
+ * ParticleBuilder#face(float, float)} which sets the yaw and pitch to the appropriate angles for the given facing.
+ * For example, if the given facing is {@code NORTH}, the particle will render parallel to the north face of blocks.
+ *
+ * Affects: All particle types
+ * @param direction The {@code EnumFacing} direction to set.
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder face(EnumFacing direction){
+ return face(direction.getHorizontalAngle(), direction.getAxis().isVertical() ? direction.getAxisDirection().getOffset() * 90 : 0);
+ }
+
+ /**
+ * Sets the target of the particle being built. This will cause the particle to stretch to touch the given position.
+ *
+ * Affects:
+ * @param x The target x-coordinate to set
+ * @param y The target y-coordinate to set
+ * @param z The target z-coordinate to set
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder target(double x, double y, double z){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.tx = x;
+ this.ty = y;
+ this.tz = z;
+ return this;
+ }
+
+ /**
+ * Sets the target of the particle being built. This is a vector-based alternative to {@link ParticleBuilder#
+ * target(double, double, double)}, allowing for even more concise code when a vector is available.
+ *
+ * Affects: All particle types
+ * @param pos A vector representing the target position of the particle to be built.
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder target(Vec3d pos){
+ return target(pos.x, pos.y, pos.z);
+ }
+
+ /**
+ * Sets the target of the particle being built. This will cause the particle to stretch to touch the given entity.
+ *
+ * Affects:
+ * @param target The entity to set
+ * @return The particle builder instance, allowing other methods to be chained onto this one
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public ParticleBuilder target(Entity target){
+ if(!building) throw new IllegalStateException("Not building yet!");
+ this.target = target;
+ return this;
+ }
+
+ /**
+ * Spawns the particle that has been built and resets the particle builder.
+ * @param world The world in which to spawn the particle
+ * @throws IllegalStateException if the particle builder is not yet building.
+ */
+ public void spawn(World world){
+
+ if(!building) throw new IllegalStateException("Not building yet!");
+
+ if(y < 0 && entity == null) Wizardry.logger.warn("Spawning particle below y = 0 - are you sure the position/entity"
+ + "has been set correctly?");
+
+ if(!world.isRemote){
+ Wizardry.logger.warn("ParticleBuilder.spawn(...) called on the server side! ParticleBuilder has prevented a "
+ + "server crash, but calling it on the server will do nothing. Consider adding a world.isRemote check.");
+ // Must stop here because the line after this if statement would crash the server!
+ reset();
+ return;
+ }
+
+ electroblob.wizardry.client.particle.ParticleWizardry particle = Wizardry.proxy.createParticle(type, world, x, y, z);
+
+ if(particle == null){
+ reset();
+ return;
+ }
+
+ // Anything with an if statement here allows default values to be set in particle constructors
+ particle.multipleParticleScaleBy(scale);
+ if(!Double.isNaN(vx) && !Double.isNaN(vy) && !Double.isNaN(vz)) particle.setVelocity(vx, vy, vz);
+ if(r >= 0 && g >= 0 && b >= 0) particle.setRBGColorF(r, g, b);
+ if(fr >= 0 && fg >= 0 && fb >= 0)particle.setFadeColour(fr, fg, fb);
+ if(lifetime >= 0) particle.setMaxAge(lifetime);
+ particle.setGravity(gravity);
+ particle.setShaded(shaded);
+ particle.setCollisions(collide);
+ if(radius > 0) particle.setSpin(radius, rpt);
+ particle.setEntity(entity);
+ if(!Float.isNaN(yaw) && !Float.isNaN(pitch)) particle.setFacing(yaw, pitch);
+ particle.setTargetPosition(tx, ty, tz);
+ particle.setTargetEntity(target);
+
+ net.minecraft.client.Minecraft.getMinecraft().effectRenderer.addEffect(particle);
+
+ reset();
+ }
+
+ /** Resets the state of the particle builder and resets all the builder variables to their default values. */
+ private void reset(){
+ building = false;
+ type = null;
+ x = 0;
+ y = 0;
+ z = 0;
+ // NaN indicates the velocity was not set (can't use -1 since it could very reasonably be -1)
+ // For all other values -1 indicates the value was not set
+ vx = Double.NaN;
+ vy = Double.NaN;
+ vz = Double.NaN;
+ r = -1;
+ g = -1;
+ b = -1;
+ fr = -1;
+ fg = -1;
+ fb = -1;
+ radius = 0;
+ rpt = 0;
+ lifetime = -1;
+ gravity = false;
+ shaded = false;
+ collide = false;
+ scale = 1;
+ entity = null;
+ yaw = Float.NaN;
+ pitch = Float.NaN;
+ tx = Double.NaN;
+ ty = Double.NaN;
+ tz = Double.NaN;
+ target = null;
+ }
+
+ // ============================================== Convenience methods ==============================================
+
+ // These may seem to go against the whole point of this class, but of course they return the ParticleBuilder instance
+ // so anything else can still be chained onto them - centralising commonly-used particle spawning patterns without
+ // losing any of the flexibility of the particle builder. In addition, callers of these methods are still free to
+ // change any of the parameters that were set within them afterwards.
+
/**
* Starts building a particle of the given type and positions it randomly within the given entity's bounding box.
* Equivalent to calling {@code ParticleBuilder.create(type).pos(...)}; users should chain any additional builder
* methods onto this one and finish with {@code .spawn(world)} as normal.
* Used extensively with summoned creatures; makes code much neater and more concise.
+ *
+ * N.B. this does not cause the particle to move with the given entity.
* @param type The type of particle to build
* @param entity The entity to position the particle at
* @return The particle builder instance, allowing other methods to be chained onto this one
@@ -152,276 +556,6 @@ public final class ParticleBuilder {
return ParticleBuilder.instance.particle(type).pos(px, py, pz);
}
- // Core builder methods
-
- /**
- * Starts building a particle of the given type.
- * @param type The type of particle to build
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is already building.
- */
- public ParticleBuilder particle(Type type){
- if(building) throw new IllegalStateException("Already building!");
- this.type = type;
- this.building = true;
- return this;
- }
-
- /**
- * Sets the position of the particle being built. If unspecified, this defaults to the origin (0, 0, 0).
- *
- * Affects: All particle types
- * @param x The x coordinate to set
- * @param y The y coordinate to set
- * @param z The z coordinate to set
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder pos(double x, double y, double z){
- if(!building) throw new IllegalStateException("Not building yet!");
- this.x = x;
- this.y = y;
- this.z = z;
- return this;
- }
-
- /**
- * Sets the position of the particle being built. This is a vector-based alternative to {@link ParticleBuilder#pos(
- * double, double, double)}, allowing for even more concise code when a vector is available.
- *
- * Affects: All particle types
- * @param pos A vector representing the coordinates of the particle to be built.
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder pos(Vec3d pos){
- return pos(pos.x, pos.y, pos.z);
- }
-
- /**
- * Sets the velocity of the particle being built. If unspecified, this defaults to the particle's default velocity,
- * specified within its constructor.
- *
- * Affects: All particle types except {@link Type#DUST DUST}
- * @param x The x coordinate to set
- * @param y The y coordinate to set
- * @param z The z coordinate to set
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder vel(double vx, double vy, double vz){
- if(!building) throw new IllegalStateException("Not building yet!");
- this.vx = vx;
- this.vy = vy;
- this.vz = vz;
- return this;
- }
-
- /**
- * Sets the velocity of the particle being built. This is a vector-based alternative to {@link ParticleBuilder#vel(
- * double, double, double)}, allowing for even more concise code when a vector is available.
- *
- * Affects: All particle types
- * @param vel A vector representing the velocity of the particle to be built.
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder vel(Vec3d vel){
- return vel(vel.x, vel.y, vel.z);
- }
-
- /**
- * Sets the colour of the particle being built. If unspecified, this defaults to the particle's default colour,
- * specified within its constructor.
- *
- * Affects: {@link Type#DARK_MAGIC DARK_MAGIC}, {@link Type#DUST DUST}, {@link Type#FLASH FLASH},
- * {@link Type#PATH PATH}, {@link Type#SPARKLE SPARKLE}
- * @param r The red colour component to set; will be clamped to between 0 and 1
- * @param g The green colour component to set; will be clamped to between 0 and 1
- * @param b The blue colour component to set; will be clamped to between 0 and 1
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder colour(float r, float g, float b){
- if(!building) throw new IllegalStateException("Not building yet!");
- this.r = MathHelper.clamp(r, 0, 1);
- this.g = MathHelper.clamp(g, 0, 1);
- this.b = MathHelper.clamp(b, 0, 1);
- return this;
- }
-
- /**
- * Sets the fade colour of the particle being built. If unspecified, this defaults to the whatever the particle's base
- * colour is.
- *
- * Affects: {@link Type#DUST DUST}, {@link Type#PATH PATH}, {@link Type#SPARKLE SPARKLE}
- * @param r The red colour component to set; will be clamped to between 0 and 1
- * @param g The green colour component to set; will be clamped to between 0 and 1
- * @param b The blue colour component to set; will be clamped to between 0 and 1
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder fade(float r, float g, float b){
- if(!building) throw new IllegalStateException("Not building yet!");
- this.fr = MathHelper.clamp(r, 0, 1);
- this.fg = MathHelper.clamp(g, 0, 1);
- this.fb = MathHelper.clamp(b, 0, 1);
- return this;
- }
-
- /**
- * Sets the scale of the particle being built. If unspecified, this defaults to 1.
- *
- * Affects: All particle types
- * @param scale The scale to set, as a multiple of the particle's default scale
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder scale(float scale){
- if(!building) throw new IllegalStateException("Not building yet!");
- this.scale = scale;
- return this;
- }
-
- /**
- * Sets the lifetime of the particle being built. If unspecified, this defaults to the particle's default lifetime,
- * specified within its constructor.
- *
- * Affects: All particle types
- * @param lifetime The lifetime to set in ticks
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder lifetime(int lifetime){
- if(!building) throw new IllegalStateException("Not building yet!");
- this.lifetime = lifetime;
- return this;
- }
-
- /**
- * Sets the rotation radius of the particle being built. If unspecified, this defaults to 0.
- *
- * Affects: All particle types
- * @param radius The rotation radius to set
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder radius(double radius){
- if(!building) throw new IllegalStateException("Not building yet!");
- this.radius = radius;
- return this;
- }
-
- /**
- * Sets the gravity of the particle being built. If unspecified, this defaults to false.
- *
- * Affects: {@link Type#ICE ICE}, {@link Type#SPARKLE SPARKLE}
- * @param gravity True to enable gravity for the particle, false to disable
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder gravity(boolean gravity){
- if(!building) throw new IllegalStateException("Not building yet!");
- this.gravity = gravity;
- return this;
- }
-
- /**
- * Sets the shading of the particle being built. If unspecified, this defaults to false.
- *
- * Affects: All particle types
- * @param shaded True to enable shading for the particle, false for full brightness
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder shaded(boolean shaded){
- if(!building) throw new IllegalStateException("Not building yet!");
- this.shaded = shaded;
- return this;
- }
-
- /**
- * Sets the entity of the particle being built. This must be specified for entity-linked particles.
- * @param entity The entity to set
- * @return The particle builder instance, allowing other methods to be chained onto this one
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public ParticleBuilder entity(Entity entity){
- if(!building) throw new IllegalStateException("Not building yet!");
- this.entity = entity;
- return this;
- }
-
- /**
- * Spawns the particle that has been built and resets the particle builder.
- * @param world The world in which to spawn the particle
- * @throws IllegalStateException if the particle builder is not yet building.
- */
- public void spawn(World world){
-
- if(!building) throw new IllegalStateException("Not building yet!");
-
- if(y < 0 && entity == null) Wizardry.logger.warn("Spawning particle below y = 0 - are you sure the position/entity"
- + "has been set correctly?");
-
- if(!world.isRemote){
- Wizardry.logger.warn("ParticleBuilder.spawn(...) called on the server side! ParticleBuilder has prevented a"
- + "server crash, but calling it on the server will do nothing. Consider adding a world.isRemote check.");
- // Must stop here because the line after this if statement would crash the server!
- reset();
- return;
- }
-
- electroblob.wizardry.client.particle.ParticleWizardry particle = Wizardry.proxy.createParticle(type, world, x, y, z);
-
- if(particle == null){
- reset();
- return;
- }
-
- particle.multipleParticleScaleBy(scale);
- if(!Double.isNaN(vx) && !Double.isNaN(vy) && !Double.isNaN(vz)) particle.setVelocity(vx, vy, vz);
- if(r >= 0 && g >= 0 && b >= 0) particle.setRBGColorF(r, g, b);
- if(fr >= 0 && fg >= 0 && fb >= 0){
- particle.setFadeColour(fr, fg, fb);
- }else{
- particle.setFadeColour(r, g, b); // If fade colour was unspecified, it defaults to the main colour
- }
- if(lifetime >= 0) particle.setLifetime(lifetime);
- particle.setGravity(gravity);
- particle.setShaded(shaded);
-
- net.minecraft.client.Minecraft.getMinecraft().effectRenderer.addEffect(particle);
-
- reset();
- }
-
- /** Resets the state of the particle builder and resets all the builder variables to their default values. */
- private void reset(){
- building = false;
- type = null;
- x = 0;
- y = 0;
- z = 0;
- // NaN indicates the velocity was not set (can't use -1 since it could very reasonably be -1)
- // For all other values -1 indicates the value was not set
- vx = Double.NaN;
- vy = Double.NaN;
- vz = Double.NaN;
- r = -1;
- g = -1;
- b = -1;
- fr = -1;
- fg = -1;
- fb = -1;
- radius = 0;
- lifetime = -1;
- gravity = false;
- shaded = false;
- scale = 1;
- entity = null;
- }
-
// Methods for spawning specific effects (similar to the FX playing methods with the ids in RenderGlobal)
/** Spawns spark and large smoke particles (8 of each) within a 1x1x1 volume centred on the given position. */
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/ice_0.png b/src/main/resources/assets/ebwizardry/textures/particle/ice_0.png
new file mode 100644
index 0000000000000000000000000000000000000000..531b56b52021c306c017a547365e2f140b1d819b
GIT binary patch
literal 307
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZfTxrdFS3UFfbhOba4!kxSZQ>=yfDO
z#PvM?%%n-j{FD|qanEr3o-kE($MiP`Q+G6IvUI=HQDW)VR7(0dK|_gC`0tDvfA(mq
zG&1^Eb|1Fw;8@kw!4SY_dujWU+d>S?3Q9F{?kTqlF7S$2Bkew~_
zggM9S<=syE?z=dDq596A<+V9ZfTxrdFS3UFfdemx;TbNTux35v-oHe~dDkMV!+Y1ym$-NQ>%a7bgoGW{-}Rd3%#mSM-gJ>$?*7mJzmDa$9ZfV|!ng1#o7#Pw#T^vIsE+;1_u-g3i
z`}zOM^Y8yDcN;1d-~03XbN$2j{yg^Y>{AkIKKCs=b!_HD&d7s%*Uy)5nYTCXNAY*Y
z!_mH}B4>H>|NZ?L|L5Dm|Hsz8{-3<{|CQ(EJ5(hlBqVl~=l?(Nz{kMA{7Qd=P0;JP
Q3=9kmp00i_>zopr0Aw9fPyhe`
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/ice_3.png b/src/main/resources/assets/ebwizardry/textures/particle/ice_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..b12745e939ce781a0af09df2ee45a53061b1dcf9
GIT binary patch
literal 191
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZfV|!ng1#o7#Ms!T^vIsE+;1}u&Vg*
z`}zNw{_p>_f1Ei%_5PpVpZ_1*Kc6Q*eossH#sd<|?e_n^|L-3s^Zm}xJZt{c%;5TV
pXV<|4-yf+u?=4qQE|ukFxa}Z&@742Qeg*~x22WQ%mvv4FO#tG8Me+au
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/ice_4.png b/src/main/resources/assets/ebwizardry/textures/particle/ice_4.png
new file mode 100644
index 0000000000000000000000000000000000000000..389abbd7b66592b6bdfc8712edbc5ffb7c927abc
GIT binary patch
literal 289
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZfV|!ng1#o7#P-hx;TbNT+Z#c=3@+$
zXx(ou`AASv`J&GgEs?0`jZD8c@ciB&V5N0eKiI?OSh9zN`S);zSwB|=&zV!hzHfz=
zE6e@~DxQUoE&-u?zRT>nTsdvko_S|Bi!d-NC@nElD~elwU3ahBnt#u&bv
n@rch|t@+{oFc+@)J&Y9%K|#}hxkfWEFfe$!`njxgN@xNAz;kHb
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/ice_5.png b/src/main/resources/assets/ebwizardry/textures/particle/ice_5.png
new file mode 100644
index 0000000000000000000000000000000000000000..e1bdc75dbac565c8c5d94de7eebc45df46b89b4f
GIT binary patch
literal 259
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZfV|!ng1#o7#Jpax;TbNTwdDe$kh}e
z!tlIXkVW!}Z4_JMY=8C_KCuf{ABo?R|8`TEqT(@g!NP?eX*aVcvv;If8}R(``d8-}
zAev;P&A{gnAbP3WIl5Sicfo6h0^hXAp5|Cw0
zr{lWWjn3nrUarvSD)64Y;am9MCZ-#2%7xS{qq6@!Xa2I=rC=M2r5XbR1B0ilpUXO@
GgeCx)zFGhP
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/ice_6.png b/src/main/resources/assets/ebwizardry/textures/particle/ice_6.png
new file mode 100644
index 0000000000000000000000000000000000000000..c597f4151ffab8cc5bb129c233b3b641eab0c5f8
GIT binary patch
literal 187
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZfU-Xg!P9R7#KV}T^vIsE+;1}u(J62
z^KN~Lov_jKv-|D;m)qB#Xb5%uc$=Lk{@=gU2LV&kGpsj>=W%iODE|F={r}bH-wbPh
je{F8;?rrYsV`F$IBXu?4vh+p<1_lOCS3j3^P69ZfU-Xg!P9R7#LhUT^vIsE+;1}kh1vt
z^X`B1|Ns8ffB60UzvlP#|MlyBH#CBPU}WI^#nJ!g7i~7=h~IxYAocN?j;l+Kt$qF9
d_<}eCgQ>gJMQ?W&RR#tI22WQ%mvv4FO#l$FK5hU2
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/ice_particles.png b/src/main/resources/assets/ebwizardry/textures/particle/ice_particles.png
deleted file mode 100644
index 96c99eade3c961c321562308511aee20aa2b9463..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 957
zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Y)RhkE)2UEx*7DJwkCaI
zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifvPz0^Fa~=}*vG)Y?B(g=7!q;#?KJ-k
z>2QH#^{YL$C8>5PORKx}{@XIaWO@wOOVxlLep``buYAofv#N_)R0;m3=WEbj-M3^UjXHY_jK|aM3BVpJ(qpnUlCsUzfSy>E4OU
zSU#UGz2iFdP3PlJr~B=~q9)gG-sx6RH!n=yVbz-bU(PS#l;O@_?snPan40>NaQ^qF
z@0tX!T620e|GRCyd;c9@zy6Ez(wfD2aWb5ja#YtAXG)^dLc9l%5txMexh~Pi_=ecPL%mqF4XnUU~||^*7HG&mi21vPgog|F{?!}TC^
zl;`sVUUn~FVfrE=+B50gi`IwB_CJ2ryt~LUJ}Dz(#YCH|Tc6sG+iy+{fBBMYTkYp-
zic2{ZJB~kIvu@oa4;6{oa}rLkTlC{^%+G?9|4%-|Tk+TMO|fYYQ~i_w+u<+gyZArz
zw&&G*-CA9==Gn(9&kZ+3KHQnS`Lf@J<=mYwugq9GE%J+V%*W3x?KMXinE&s|iq~(R
zc6en%htt=5J=ODXG8yX{!c@Ol>s|foWUczfmf8AG4*TL3KC2fCn)c{xjT=e*4d>
TIr}>U0|SGntDnm{r-UW|XzIi8
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_0.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_0.png
new file mode 100644
index 0000000000000000000000000000000000000000..6c1dabf2c8c5534f2ed11fe1485825402b5fb788
GIT binary patch
literal 196
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=eE{Yo_Ugifq@~=)5S4F;&O6=g4hZ1
z6Gkhxu1e@IKB#ij^`>N8e8t&Dju!7*9-wC2;Jzd)vYy85}Sb4q9e0OjaIJOBUy
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_1.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..990fba4b9a20f30668c5755e564f7cc141052754
GIT binary patch
literal 187
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=eE{Yo_Ugifq}up)5S4F;&O7r0;wGp
zA0O54;d;WIBB>X*=g0s5|Nm=n%}nU=_qR8U*;Uf{@X}Imjb(<1B(m0O@vPV1la`Q>
ikWjJzm-5#;=NK4_x65pwloB`%WT>aBpUXO@geCy7SwCO^
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_10.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_10.png
new file mode 100644
index 0000000000000000000000000000000000000000..bdc4dc438bfa86c56d20384525c5bd9168fcfa13
GIT binary patch
literal 184
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=e9PyIqgd_0|SGrr;B5V#O34!1@@Rd
z6(9H4H0m&efbgy-|NsC0AHS=F^IZBN_0B~MYAcs7Z@+yHEV`${@J<~MYlZ4YF9QPu
b28Nh>dfHpyY-sCq-=2dMAygwO6J;Q2ZczyYlwVi7FGGu(30o;ZaFUoABi4#@&-uwrv)C
i|Kio8fY2lF=R|H$wr1(P_=bUjfx*+&&t;ucLK6TG6+h?z
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_12.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_12.png
new file mode 100644
index 0000000000000000000000000000000000000000..abc966748735ed65bb9791492de577f78187a93d
GIT binary patch
literal 191
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=e9O-n7{NU0|SGPr;B5V#O1ZU8+jWX
zc$j6`yuK|?=6SW|6Ssw_Z1W5)p*=4SJe{k{9Pbol=Ipsji^0L=#wWGAvawYjlO`=W
o6H@$o{qILIv)BG^tS@5Rb5qB9|JBn@3=9kmp00i_>zopr02Dz$K>z>%
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_13.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_13.png
new file mode 100644
index 0000000000000000000000000000000000000000..85124935f27096f74edcb5c5cc4186127f47e40d
GIT binary patch
literal 180
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=e9O-n7{NU0|SGjr;B5V#O0-@4ssqa
z;9)sv?O_{qag|42#%CdmO36L?ozgFtynDvM_~)bX@hI;}B7#gC-tx~VeDLJ&O0BXv
dGq08ESL~39S;<*i$-uzC;OXk;vd$@?2>`qLJAnWI
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_14.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_14.png
new file mode 100644
index 0000000000000000000000000000000000000000..50a9fc7007a62c3b58da8b13bd85d7ecf9a1e544
GIT binary patch
literal 181
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=e9O-n7{NU0|SGTr;B5V#O1kt2YDS7
zd7Lg<@JpAz*d#E|#Pp;5zV}xcR2lSBmR+}9m3VuSLT2{gZ=p9CCrx0P+fq|jH)5S4F;&N}_M&3gP
zBCO{*G*f4#G=Gt6QDQx15D>xDDqa|s=6GK>=Yh_ISAnceEiB=-wy}jDn78v8PyT+d
z^@ic})@5sV%#nW+rue*PW~R;Et6N0Nv>EafPk$`9dR#Ec-OF=QO4_6^Lf;sQBO5OI
q3jd0dN^-Zq^2PbA*{u2sroC=P_j>I0S28d#FnGH9xvX|#sK7s%M
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_3.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..d2a7c3c6244a2ba1b913337413cf11ae64e8d0c6
GIT binary patch
literal 167
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=eE{Yo_Ugifq}uq)5S4F;&O6=0(;D!
zijVeTo&W#;|L;CM#VNexU3>lPMC6w}y$n>C%ha^W#4VusZ)V6xD(99(E->>M>}GTFvFWHpVu_$=|=<
iF+P6FtMhQc?>PTm~{d>9xQ7(8A5T-G@yGywp}K}53v
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_5.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_5.png
new file mode 100644
index 0000000000000000000000000000000000000000..1aa1c4309daffad3525edf44c481244325ac1ff7
GIT binary patch
literal 229
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=e9OjH}S|<1_p*APZ!4!iOX|)cXPHl
zh`9DA=}Aj;bxNGeG5(gwtyE?-(d==x>I|;mD<4Sq8tCLa=;ga3e`jJx#1k7Q^X(?i
zy)$R7ihHPZXrt_&Y5qxS+zhL_iuoGc?X3Gp;|rdsnbmpw~|+shosa%dU#lP0eN1T)H9d$(-ySL!M&(W3MyH?LxfO
Wq)jKxxy``9z~JfX=d#Wzp$P!TUr{~)
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_7.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_7.png
new file mode 100644
index 0000000000000000000000000000000000000000..e0a4a7962ed6d8055cdbec20dda86f05ce4e7ed8
GIT binary patch
literal 232
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=e9OjH}S|<1_p*wPZ!4!iOb0e3alr@
zPZ*sLKe4F8(8$2RAZAa+$Nl$fVqOX=K%sJXE{(pbP$4B)N0okF60z6OC
z6F{Kx<%P?alXsN76k=v(W&Imv%2X=zGI
zbvNdjpUG9@X}tdNu+noM&7*s6zspPH*s_vw14}??*4iI+uWny!4-NO!EL}JyNw4hT
z7YSB_P}fk#T^j!)W=l=~do`xluuI$iH`DQ{UVGMTSf#?iz`)??>gTe~DWM4fi`!bn
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/leaf_9.png b/src/main/resources/assets/ebwizardry/textures/particle/leaf_9.png
new file mode 100644
index 0000000000000000000000000000000000000000..29c3868df82e4a2dcbcd9235e337ca9ca7694a57
GIT binary patch
literal 243
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7BevL9Ry*<9TT(PGB7Z(mw5WRvOi*H=e9PyIqgd_0|P^Yr;B5V#O2=JoxDtj
zA};eUdaXO4sN~op)*8U&bVMNdWOM4gVTsnU_n&Ghp(}d!8v#u3<-oPDPBwxktgyT1FO1rbDi!z>c7DCqo24B
zbKolHnjMR!xMn2h=U=x_Si>Q4@=|4bT6$U8z1ghix?A=#oK4&^Eg~v=+WRh+^`==T
z(jpyS7XK2pWiT+#Uc2*Z)=DQPp+AQ|`|})#>|C3kyL4+>S{a*?Qpde?<+9mxtN!ih
zVp#uv|H-K?EjiPs%7`!L76`11`Ygh*!TfG0yG4qUlg#mZ54^o4zA?4zJ+LyLPdTUT
zRqLBv!P*<#Ug3+jK2!0$@%laYA8X&g@zW;RE~Ql9_BJ(rfpe=GOxH}d}T;gqtOY|f^OQO1G~
zKkjZkl_qJ|XFt6}>2BWk2eVa9UfLU;XA?fZ!>{ASb?3CJVKZg_cifol{UB}H#jVdi
zl^%STzI5G^%qWS)kH58~+RPSMW11zgU47@=YqKt!l**mRackU>KPB9^B1lPcJ+3D
z|7-TL|Ie{^+_@Z?c{x=-`)^>2bvg4F_rOA_T~={yZ3#E?{N}Ic?~2NnyEFUqQa9dT
z8rtd#7G;TdWVY%#S$a>+yEkKldA0blT$$ZXx}V?oE9vuxs8%lwRXTL?v}0yi{rvZ=
zc?RjbLOMFU@*BV36lY+by6l1dtu=Np`;~IaU)`|lf8V(N+`BzjmBQxqGB7YOc)I$z
JtaD0e0s!9`VEF(5
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_0_0.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_0_0.png
new file mode 100644
index 0000000000000000000000000000000000000000..e8961570f2e981b36b7fd73e0c8942199a073557
GIT binary patch
literal 299
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgKGq`#ks=7#L(TLn2C?^K)}k^GX;%
zz_}y(O3Z(G%s9
zCfc48N`(FdoPJWGsIh8N$1UN_`GU1oyX-V(#YTvjZVGD9ZgKGq`#ks=7#L(TLn2C?^K)}k^GX;%
zz_}OC9n!DV;&3>7=S@wiN<*dugzwL|Xu~PFob1LQjtGZb^dE2)1
y-sJqwXY%W~_rE9ZgB|(#?W~T3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*Ru*1{EF~s8Z*2#`S%z^^0`==Ne^69z6cN7<_
zJg3CrbY_WGSg^_e%F7H49Gv_6Cmc9aZ>OTN{kB${b5B#p&U0IQbEb$JR!8`Tdv@$D
zRFk;4a!I{Vk7>iz_g5yp$$Io)$(ipirLl*yI$HNUTNM3T!{bN{huE>-Q)cGqO}Dmu
zdXK>&N95}Jo$oeomEN4b*oNV{?3Z1aHokN!@_rNe3m>%pU1jaAkTTa`njxgN@xNA43mDL
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_0_3.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_0_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..b78a86ffc0ea7f82be90dde28ee6e692ffa060df
GIT binary patch
literal 337
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgB|(#?W~T3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*Ru+`JWF~s6@Z}36EBMKaM?!@>;wTqRg@J_Vy
z3BIHJ%0Nry%m;zQyRo7S40;jAR$Ga8oVc^*weHz}=>l25PuqPyV(sbT(tIP(@z|HP
z{n~Th?)frFrFHN19SoLoddz2CPG>OcnHWpF_$pldruuf}+pT3YZmBP4SB~Flf8o8`
zx{&$_$;-7hdxT7`Ci7k>Irqym=m(?1^GDhY;vQVz6Z*6rJ~h5so)dTf^9Cjc@l8Ho
f_UE#GwE4k&E$>syME6A=AfI`<`njxgN@xNAj{kX;
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_1_0.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_1_0.png
new file mode 100644
index 0000000000000000000000000000000000000000..60d2e3d2d06ed7d67d4d84d3b295a6489f156570
GIT binary patch
literal 315
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgB|(#?W~T3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*RFyGU~F~s8Z(#aPETMRf{%+14t*C?B{n6;E1
zS+;}Uuvu>2lPBtllVau0FjO2AtxaT&QB+EtEWX3Z>l00P*z~^yVYRxlAiNGsQa$AFp7!-70TdM!HkN@`8ulls7$$_Z{rmnG(y>Of{{%4uG
z>Z~alm%djk*`|9ZbY5D2cfzFGHVgr)cWi$s^k-v0#imR0s)-BV`doTx4Dy4gtDnm{
Hr-UW|8GLJg
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_1_1.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_1_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..0d98efd635c912585b96c3487f16a281e94b3ebb
GIT binary patch
literal 355
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgB|(#?W~T3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*RaNN_yF~s6@Z}3IlRs|lL9^->D1{0>X7Vt%^
zdhh&1bd8sA5ZBA6?=%ibXwJ_zns!aasM?x$lfu*IZJBDC%`naKMdjT4&ByzZjui2tEa1<%Q~loCIBxXekA|^
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_1_2.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_1_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..19d23ff3afacd87655c4d4c9a723026062dc0fc7
GIT binary patch
literal 352
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgI(Qwp0!V1_s&8kcblJ{M_8syb=Zw
za4t$sEJ;mKD9TWoKYuIO6Hz7-DgH>g3ykM-(_*^)*jjNt6oOrm)s|
zc2a!-d(7t~wZ(}n=UG|8!lEvTp3h-<5$ED^{kDpR
zDjK|9?}gT>>i8rvT($fC$@Z+v!uw07oMmxNN?2v<%_Dh0`R#1ZvQTr+8Cm}s9)x;(
z&OOP}n05YfeDmbhXE*+TJ@1zJm(MRcKJI*|WZrrFoUq_(9XS>+4%_;BotYbM2t_FE
vs*;Xsw&AEV=i~Hl`n>Xp^=JJrUv7wpu6q9R7~7;PAdh;w`njxgN@xNAuE2ku
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_1_3.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_1_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..ab8dbf037ccec30b0c42c9792db459cef33ae0eb
GIT binary patch
literal 346
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgI(Qwp0!V1_s&8kcblJ{M_8syb=Zw
za4t$sEJ;mKD9TWoKYu*yriu7-DgHYVd8r!wNjYG3kqnFSN>tDHTsx
zdZnK!T`n)`|B)X_o)K&}T=kmvJDERGQps$3VkBc*BzUYKM>=Y)=~Jd-8ya}l%&lEh
zJFBSioUg#w#|$eNZ(YCdqs~~sa6p2OA*guAXQsIGYr9<61tp)zXP)&$(qS^U)}6|)
za}0H4tZ(wCPEY4q)F{=#c27?*dyD7!>k65-o-gzDDLu64)6=NE+jbbdbH4OunbKj-
on>!8nwCkT;mRhb~l=@Tgp5$VVB@FVdQ&MBb@0PiPy8~^|S
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_2_0.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_2_0.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b189159fe0ba8bea994cb30d62646c764928406
GIT binary patch
literal 301
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgI(Qwp0!V1_s&8kcblJ{M_8syb=Zw
za4t$sEJ;mKD9TWoKYunCR)^7-DgHX|N+-g94BCG4qGkADj=gKal;g
zvMO?lf<}U{kkhqNZE1t933V*(ER*JXo_fGmnK`Mqt&4p_{(7s^CXrf^)wMe&JyQzR
z{}lH$&U(J+g$#xrq239ZgI(Qwp0!V1_s&8kcblJ{M_8syb=Zw
za4t$sEJ;mKD9TWoKYuSm^2E7-DgHY0yEz!wNi;i)V5^YiMl}Z?a6#
z{C+X!wX#L4n?7IkG#!SpiLaZV#V9IGcK(&tyhk!++5?BBj2G+Itu&bzXy@WG;dSDj
z&2jnjB{>*`VisKzVsKkG;eo?poh{9u*EGgNrYBlWcyMWF`75tAn-_Nfy8cS~;(fO5
zGpD|gy!cu53}4CWb%%dHWLbQm?Yw14!iw`L8`cXwtH1YZLj6j8@!#|QG-k{R0r|qy
L)z4*}Q$iB}mMC9ZgHt|{3e?i7#L(TLn2C?^K)}k^GX;%
zz_}=K>
z@@K4^iVK9Rqc)XA&t{Bwl(~NLNT7?0`4V;iBez4|9ZgHt|{3e?i7#L(TLn2C?^K)}k^GX;%
zz_}bP0l+XkKFF9ZgHt|{3e?i7#L(TLn2C?^K)}k^GX;%
zz_}>0pL(PJtkyJi@8%Pq^2L^@#?^NJnsg)l!LpFE
zi$Y6`XK-8!pPSt5y_EBYx*=2c6G6H9gB2V{WI8%jPAC}{tPCk*I1u^V+4#VlsDm%o
iv`p*OToCWT@PLI!a?{6mGy1zgZuNBab6Mw<&;$VK>|ufc
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_3_1.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_3_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..bd62e1cad475123ac8513ecedbd5d6d68b5fcb26
GIT binary patch
literal 328
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgHt|{3e?i7#L(TLn2C?^K)}k^GX;%
zz_}Ur
zUD>O<%sIw!AFqy*_^iw4=610a*ff83EQ+tl?aN5jWR!ZvknO8|n<=C94$G-aC*74#
z=Xlk<6r38ZF|qb@-aQSCH+Dupf5hEpY{<%7@g%2V=HBpv@9W>(s$lsdF2L}EftPL1
U?3)>#+d&@kboFyt=akR{08IOEKL7v#
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_3_2.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_3_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..e5c306fa53cf661786fa75dfcae71bf0045396cf
GIT binary patch
literal 319
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgJ_I94smf3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*Ru-MbZF~s8Z(#a1w8x%xZ-gg>bmDw7wYr?sO
z-m&!|Z(0+|6j~nKt@UT#;`qLc6IjIB?)t2{xXbhUv+bM=cRVY%*B@q|X9x0!
Mr>mdKI;Vst01kL_O#lD@
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_3_3.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_3_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..ee15f8724ab27649aef79244ce1523d6cddc5b4c
GIT binary patch
literal 302
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgJ_I94smf3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*RFv-)!F~s8Z+R1l$8x(k2{M!y$mMEqu&S9Ru
zia+TfS4YNVHlY{St?L*h&q9ZgJ_I94smf3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*RQ19vD7-Dhy?WBW(41zqa`RX5Z&5ZeXhV?f)KT=ZC
zYcUa?FpZDFKArcD_Ey^tNL!mw9ZgJ_I94smf3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*R(CF#n7-Dhy?WEnj4F&?v@hWLemI;a{oD%ys
zOwl~CkU{X#<$wgu-qhc9jq=YqHtyHkGQDt82}fj!z@xB?4GVfLwI@{Qb2=S)8yy9ZgCm)oQdrW3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*R(C6vm7-DhyZO}npCPSWLm9(tq8SIPBIwkgP
zm{KXD+h{FYpf4BE6%x7esS4}A8|{_V*Nb+U+s&A@e1>YNA$!&}-^;T^4cJdc8pIz_
zN#9&4eUxE_d88`C6xF#;i{3UTcz%|xys~DKp*h1A+ly7~f~WaHoK_`%OEEdKe9ZgCm)oQdrW3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*R(Cz8s7-DhyZP0DrBMLmlOJ;LEYiQItZCbivg2sg8o1$koGAuGMt`{gh
z*KW-oxQ$UD^_JBJ5e9~k+eZR(j|No)=bnDiP*&vcByBkFQ3bnl6?@5pSFcQM>|K7I
nDcv`(ROiFL`#bjjnI6HYvw9ZgCm)oQdrW3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*RFu~KsF~s8Z(jZ5^!wNjbtM+#8ZMMzmvDMh4
zTyx6WXX-9Kj@(*L5y9iz7~BH9EqJ%OOp-g<)V;&!!Kv>#ccf0wG_+ZI<$57^7Q=)k
zSIiq~&a9I1XnNxHWo_2abhD^?*Yf_SJM#8024(#}@R(0iv}fVs6zh^JZ>H+JZjJO<
sDf~WqU%TSDma1>s{f9s2Z22W?7q+{NGc51WCXk~&UHx3vIVCg!05$4qH~;_u
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_5_1.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_5_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..6607b21f69b726bba24357ff416213d8066756dc
GIT binary patch
literal 314
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgCm)oQdrW3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*RFwfJ)F~s8Z+MwHlM-(_>j8=NSzR-51Z3~~~
zs~!C|&%P-6>1~haVLq+Lka5EFLHZLZ7nd{@Zn;N>2SfgyIaYM@jn9%pANRG^=j@$W
zGgaDTx&HaZI}UfnD4t`{`Xj~n!R%s~xMui)+gG$N=ugmgc@l8z%KG0e{<~aS-Tw=&
zCMHB-&=Ncv3==b8a2;6wVpy6Ouj~fxO`9>gTe~
HDWM4fu3m63
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_5_2.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_5_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..706d10a143326c72e17759947dbc0a54ca2a0bf9
GIT binary patch
literal 298
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgJUw?1h313=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*R(C6vm7-DgHY4B~{!wNhmJg(0dFtesB8n;Kj
z`sBQ*qiNyEzYRKXsu^6wTwYqba2_b>SU!CN+Y<9n!VFiwp4Z7ctKy}yE1J3H_MKY}
zJhx}fJyo-@KZ|>w|IfdF`&loxNZfdO$hql#dihR+qzC&ZRTnN=7W&A)?W%Xt&JTZT
r&Tp4|8f0OLJGsk{3##%6Ru3dY;d&z^JASZje`njxgN@xNAi~Vii
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_5_3.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_5_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a67952bd9672409682aa22f668f9bf5973e5426
GIT binary patch
literal 298
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgJUw?1h313=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*R(C6vm7-DgHY0yQ%Rs|kzzSiOoY(g1@UiXk(EYg~VgE5Z
z9fdxHILDaZ`(I`7-hUl-wsiSKiL7&*r={?JG+#fu&CGM9)iStN0O`dpBcJzf1=);T3K0RXi)VNd`7
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_6_0.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_6_0.png
new file mode 100644
index 0000000000000000000000000000000000000000..07ac3f770353bbd5c0d58d14ad64e1157663b4e5
GIT binary patch
literal 291
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgJUw?1h313=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*R(C+Et7-DgH>7={74GKIh{*Qc&+I3uFIG!I^
zdX9a`Kjy366%9{*eT{0E4`T
i#c-4_`^&TV?}6IB)g3)=SpKwu-0JD-=d#Wzp$P!O%w>cC
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_6_1.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_6_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..c7a7d8746bc7b78c057a48f785effaf6655462da
GIT binary patch
literal 313
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgJUw?1h313=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*RFxS(?F~s8Z+)06aEebp?@@eOnJioxLSgl~g
z9=ED)gM^9bEut?#2cHu*Oh1CZc0Jhkm%C*i
zbFAk4sU2O-b2hL1QhcM1S+Fvsa?NaZP3xMKc`|dZUtylGYzgb98y~KLeBkNo=d#Wz
Gp$PzBt8X&^
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_6_2.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_6_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..3dddd174e6b1d1a67753ca6dc34391595e7a0122
GIT binary patch
literal 312
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgIJjNgq}-FfhnwhD4M&=jZ08=9Msj
zfOAo5Vo7R>LV0FMhJw4NZ$OG(Dmw!M!yHc+#}JFtODCP=J)*$lYOi7HC>wBrfp?~r
zPvGO70+W~%PwrW)`rp;epvl7KjA6S)M@NH2!;dJXwvL?cCB>PwKjRjwz0iFfDqF~=
zC4S(x?(?uj>un)(^b
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_6_3.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_6_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..e84fbc4d371b451cfa8bf9be839e6c370476922c
GIT binary patch
literal 304
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgIJjNgq}-FfhnwhD4M&=jZ08=9Msj
zfOAo5Vo7R>LV0FMhJw4NZ$OG(Dmw!M!xT>!#}JFtOM`Cn9#-J7S#)N~xrusDHVB+y
zbbk7)u_NQvk-X|j^*Z;x8SW@fegEyb@}##r&R4z{eYtpIv-^_f*G&_&Kh((V=Jd-*
zxm~&9!Rs|8@~tKlD-}2!eu#-@O!WO8(xNia>ra8vyj&-(L!~#J)=4+ST667mGd?)M
xN$*nUyaiu-esH&)etPfk#601sclWsV2gR#S=#wmB%bo{vxTmY1%Q~loCIGnZa1Q_g
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_7_0.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_7_0.png
new file mode 100644
index 0000000000000000000000000000000000000000..7bc98d4e0bfc28f39013bd482952ab8e9b98fcda
GIT binary patch
literal 313
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgIJjNgq}-FfhnwhD4M&=jZ08=9Msj
zfOAo5Vo7R>LV0FMhJw4NZ$OG(Dmw!M!(2}n#}JFtdnaAwJ*>dv(!av^pv(q=M8$Hx
za?S6`en}jenMzmVBR=#!Hu&&eX&9ZgIJjNgq}-FfhnwhD4M&=jZ08=9Msj
zfOAo5Vo7R>LV0FMhJw4NZ$OG(Dmw!M!*Wj-#}JFtdnX;_J*>dv%6rPkfL$kLkH8s5
z@15*x*g94&3ez-~*?assd&BU`wyceVMV--7L53HXJTEL3
zGB$qFW#oQyGGD)Q9*^_i$ORPz$syykz#iysM
znIW1}|Cpn=fRka(wLc$U{^j6MQVPEH^q?q+U7OyS1BkXunR3V7Y%l-?C?x^`ym9
Qv_XFHboFyt=akR{0ACqzGynhq
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_7_2.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_7_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..249ea1fc9481194a0e03889a9eee8dcb470a894c
GIT binary patch
literal 328
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgIJjNgq}-FfhnwhD4M&=jZ08=9Msj
zfOAo5Vo7R>LV0FMhJw4NZ$OG(Dmw!M!x~Q)#}JFtdnX?hJfgtiYHz*rbP0l+XkK7esl+
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_7_3.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_7_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..a7e8abb6fb78b65e2ed76597bf4217785e6aaed7
GIT binary patch
literal 326
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^Oc=AWzVXw+svn
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y&>9ZgKg2sRwKs7#L(TLn2C?^K)}k^GX;%
zz_}J=a*G
zw5OOMe^YY#{co`b*y7{k~5n?_blFW$_=G6f0(S
TrDgmn1$oEQ)z4*}Q$iB}ThDYf
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/lightning_particles.png b/src/main/resources/assets/ebwizardry/textures/particle/lightning_particles.png
deleted file mode 100644
index 94dc49c5599146bf0eafd875870a572fb499be3f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 2602
zcmeAS@N?(olHy`uVBq!ia0y~yU~phyU})fAV_;y|-I$-nz`($kyQ7w
z9zExIW!^j%&VJ4v_YT>dfBO4M^|^zSD}L1dOWwcUx5-VWRiCrtk;7Kc3u5l`TV~iF
zzi-_t;Pm5<$KkJH&rVlLZQ~FAm%eY#;ex%bAAULtJ3K!8q4xZb%%Ap#KQ=sIKHy&P
zKXd1P_W79|KmUDxI;ZWuwSC{7NvE@xRnDt@!};NZlBL75mXL?Cw;BIC@*TL&x!3RT
z_u4bs3}GAQM3%8#kDUMD^&Y0f-)+~nIIYv#siyn=UvweEg5X8Um**a5wD?e{-#2;7
z-X%pWQ&_tnFluio5>=gY;k(kKX&shM!ZoaGS>`=v$W8T?nXt1hqW72iw7;kCt$xzS
zS&-%FzW4j~-#YWxR!n2A3KgC4b}IL_?~^^JDd-)Tv+!+g(6t>QwrTSH8=G#doyD?T
z!S#^wDlL&5>mT>J)YkkK_7{I>DR?vCmIeaw#5BSQ+3rA+08Cp|-7uf^%Z;
zHiuO#%NMcUu+7{X7TaBSxklHFwN?Irig=mlTF*^i{%_6@E;~Qp;&4++eV#((+FWLT
zZpCB{#hE)fe3&+AC7W7$Fs%E2{{3`eAyqvCX|YMg7nj=gwoO%I>HNL=$K*o$Pud=5
z>)L;b@M?S2-h7uIP#+h5`PbaKaPzWz_HxD}yB
zta(4SE|~s!Q;}$0;fh5PbL)J*Sj3;3xbVIp!@;-&*##X;c8@&xI`!WN*79X|s?-|I
z3pqZ=OxmMdd|zBxN6f`HF$HUW9!TD{?1SKrgCFWLAMSHm_rfi|MM@)igIVIowjWW4
z*w{*ij<{BKiq30&yrpB&{!o+1lJ$&jCC3HpCcH^CX`UEkC^vsv#~BxoBwqPOo*Ao(
z8T1YWab50W4*A2#K5ga8@0qL5rFNEG+&@|V{_o114v+Wl|1YbhmB;UA&$qm9FD8F;
zZK1_Hi^Pw7`-J0#ZW~l^*M%IuquY4qwQk^#uO&Amo=EI_9~`W(nLFRpa^g3m?Lh(d
z-ybgCF}<>;(r#x>-KKYsot8iPTzl9~r=&{0E;{k!n)yrY+n%oIJ7M|YtLEg=#ETCn
zo)Gi2tvId7*<-ITOZeFQBODW+c)kpjJtypQY{i5(o?P1V_c}HG)BT)skbeqiG>fv0
zlK_`I^FsCq%-R3UR`RWX==At8|D)TVq*^NGsGIaDZ@71%Y$nIWK7QXX^0Snl$J#nY
zM1D+5>}67_c&~b0Zqc`O>HNXf;l(pc_jLXX7Cw0CYCnI}pNk#u1#IlQ?bRZGecv@>
z|AnJF!;`)z*bt2cee+gu+1tgEbhaQymn
z)|S#tTmOQ`i78X9lfu567rOBEFXR28ky80$T4LpvXGe-RT4zt=IQ2F?%<=wVBRi=N
zjVnw!WcE#Aw7qn{t$&i{UDdypHIsBsPc%~9sls_#!QOtGO1qW4gM5npyv6h9EV<0(
z6dLZd%ymuL<|EIIf1R8nKY_jXQOVp2tzeb4CvS(9PZH=Vny3=`Hr2Ow@#A*iidQBx
zFFUDUoa<8gE2lrLNH3vZA1JU3VGW9CYm)!`Eho+sW3TzWs{4Lo*X&!?ZQP@KJa#mE^O0m)URpPI%|Jr<>$lS_nwRS`^STMd%oE7N7?)4
zEPlO5_JQl7)SbfCAMY%3?MXk+#=1X>w}Zjvv}llna?1p(k3asE{aSnQlAHPp@%+^a
zmz%e4tW??+bE>YUw~PJNXuj`N3(>-}CJ{(s-S>)Ah<^ku$OOx$q&$19(Iv(**s
zO5ca`a?Wed-zdX;-7)BSgZtLwDVug%KKg!Gy?838%$_Q)Bfba1PW%x)^?3P3uRrIa
z4u@6kpL|6EYU^uYW(Rep&wO^3I;KkDmvpmb|T~m)!UI
zC)2O~C29*@zO&@NWSlUoMXNCHh4?95-?JQ3uXMh@g|_)tKGZvs7Fb^_pSE+*x#`S`qdWA6juDa;PwZ>
zsH$&v40d~N1OzGt{n>NG{gh7Vhb+UbKP>ytADb1_e&*;`*;#UaTm*(+@_qaraPoDoFz~;k=
zhc_SoQg+tAxac%H=h3$B_ByTAvyMFcF%YHDiTh=6GMQaOCeXX36apU~O0vUS~*tc_EC@obd$;B?ty
zoVBDY(dqu_>|1J8>7R{6Gta-{|32sc!#l;T`3|9z4=jI>$yk`+?ZW4G-mJd4hW7<~
z%!Bv^)&kZ{d?BWqO3}TQk6AW)hbAA`w`!YZU-A05_4gxUV)ks^zrUXKM$lDG1yPGX
zS_@XiI_Q6pZg{-^r6FKW{L5aPHy5hhIyq_S%}8
ze?NWb(4m<@D^qr?)86;KJ5l0M<-Di6-uWvD<>%(sGK$P@R9jG6UT(f~&z?E6=FhjE
zfBw1iR4-R4$51WN!r1E?(@*$3&iYg?Tbu8z=g%eig0Dfjn|7(MU9t|n4fBXr7aOifM0S6}71Y+}3M
z8iyh0osg^Bk~UT-PCp$xZ|2OOmFelv+uLRzJb18QS6A2c^rk+enP=V~n4BqPR
z^lD=0-u;_4eX6Oc*|TN)_U{Q98805cdGqGji4z^mS8X>pH)^h9#yV^I|)r!F;Vg35`@AV&~
zTF88>uBs|?Ny$z~co1tL^G`(Ozj}bc#9Ri;QV&_BO>0;Eb&xV>T<-W;kLkSYle3Ac$>ecnno6XwuWY%-z
zM=xeyNfA4GYt|*BZI?qOHKtx_^)`1s;wu*W&HqLG#k?4i#5)=y3p1F-qzu@)m8WH8
zCtIsLYF=I_WOULd-`tb)QKYQi_wRR$`R}XW369E^&R|@8K-z)X!9}b5{VCZ35ea6I
z0!ACAO9yxp7*rQ1DaG}3em|&}z$}@th`Xh)uW#O!*QMEcd3n35<*r37cX{&jKU37}
z!UviLH*(DGTiM&s=W06OvHWs+f$rckbMos=a!S0v$oG%8H6MZQi!++udi+o-N-Q^Uh@U*?%lKEv`>m
zuk8}xYMmFh`fA47u{7mu#utR#S9avlW*U?{c-fD>x%E^%XaHBGc#)}&C9+0&Z6(K$I_sAnX{f62<+au
zvoc0&>OFn2Zhr5jL4WM>CE6N;v?5|+{v0j68!Twa6xZ5t{bI%zOB0hT+jLgvMqYdE
zqEsl|f4r2x&u#IoO>3eXdV72MyN^B+ez3H|hM)O=mxt+0pI_@KJ-HP|W
zkDWSo>bzP
S44ofAY2DM+&t;ucLK6Um(}o=Y
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/scorch_2.png b/src/main/resources/assets/ebwizardry/textures/particle/scorch_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..8a908c4359e903e7884011f9315c56f39aed63ff
GIT binary patch
literal 874
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^MeG;2pW})eH;_
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y+NfF+q9eyI#5s3=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*Rbk5VoF~s6@?&R~{%IOlv?eo*_te9MGP@<+N
znv}8m#ICZpdESb_nn6w*-9J9My1G5CdPRGK`2VJVoNrSXPLZ4A?V9EILQ!)|_nIX>
z?Tb2Z8BG3}Sf2dlt*Yjxua@@rpa1+&Gk^Vqc|l%h8QwFoeGuBgXrg%J=j^?Ycps_+
zuw^v}9{*S!bn1Nr_XFn#>yO6c@lcPY!_3PK=x8BZ8E-Tx%VcWKEOh33Qq<66R
zl`g%aGlBc?g|gW1-D#U6E$r;fY|hW_Sfp_|$Lwv5UA?sH#BE!*US-ufz!DJXRlA;f
zThObMM~}L0y!`UXuDkD+y#Fn{?|t^)x_AZ_M+KvqJiTs@Kc78&_S2_NpQbx?%s*zn
zVY151zC{|dm%VJ(=-Ohyb2Nfyf=cI%`Sa`d?%w_T&bGI~3sy~G`moh)vEkgaX`xGl
zJhi5Jg=mNvt$QtY$l%PKtrot)e_y7`r&mYIgGdeeiKW!{ULR;s*IMxxDd#;jRhjq~g_t)HjTSt9e?b!Et__3PI8
zy?^t@MkaX1vX#@OO^eIT$(iF4Xp$Kjw&3+H{y(~I^&c1?^mrV4`}Xa6>$!emmrbs|
z{wgVdX%{~>^IjBksq-fA7k$P{JXtj$Gyueh~iPX~x6LV0FMhJw4NZ$OG(Dmw!M(+p1+#}JFtrIYV^PfnCLR)5~CxNghyyE3aY
zzlhCXi_TcjTsosxK&8asgM-z}1I>KDv^RbJC45NO(8|lT$>W2A*4c-*I>lD1-t3q)
z`~0%Zn>(y4d4+fT&zt;uSH-*8_m^5Exg24NYFvN7Yy<0@0I#*O*H$U_EN@`A!1$v<
z+<_y5@siid?d-PmnA4;)3XaMin{ngHl`FamQ%GVYf&C7f(g9C~{*D&cCBi>AdrZyD>gLRt;i03W^CHJAdal>fb#LCh
zsR#=Td)L$7fB*c`qV&eg2UrC+PVF$+nR&8k=bb3M>4$&T*j>4OyZWxgVumf(l5UqB
zEu3?A-@bk4KUVxH))A9te`fRU9j`-4X6DO7Cr+GL8lqL2d!HwvC-7*}#b6z=y{Au~
zKIpY{QG?Kicg(LEyDwk99G;$@etya2%vurYxb@SwZQHgs#pvhBZEr&p#6SFQc=uU7eIzqQ&n?Pq-7=zrkRuU}Qc
zN)t7XByBw2>5^1jQ1D@?;j*pUwtZ{#POg(zna_P`Sw{%-`i5!Go;{oDppeku6dry(
z%0NOVW9@zBs|O?kmQOh)AG)kc;icHC-s~N(?lp00i_>zopr0I*$s#{d8T
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/scorch_4.png b/src/main/resources/assets/ebwizardry/textures/particle/scorch_4.png
new file mode 100644
index 0000000000000000000000000000000000000000..65765f7b4f938d34d37ddbdac11e7c79a896c293
GIT binary patch
literal 848
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^MeG;2pW})eH;_
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y+NfF&;*?ebOMKWHUn|N}Tg^b5rw57(l?e
zC^fMpHASI3vm`^o-P1Q9MK6_|fq`j@r;B5V#p%+?_8HRY636Q2zw_z4<657@I#3s7INATR;Z;Y`=w*Ia_#G^OwqIRllEdG=WR4l$5gtRmpQlP8LsUL@(2mu
znIL+6j$Ww!%arSz7VXwQ%_(DEd3^f!?;q^;oY$`K*Ic@e*{VP@YiXl>tHA%5IilhR
zqz_mWNWWmLXAawcfBv=7znTRsG8~Fg%x?DV=?(qXbI-}1-W0Wa_wM;migt?s{{4IV
zuDkD+2Ccl(_u#qL%GXXE;qN&Z7$hslm=UsbQ(lc}B%;|lPa~Sr&nAp2~Tdw)_
zYuD=5glL85-nLtP{dLstyJ8GMUK_V;37Ii(-n(<>&tI20zLN2JgA0!b>iC}C
z-cp9GJ9o~MIlyrI_;DvM$;m-kXVWgPxte8}AhJWK``lF-Ik~#GzxO@-z3<*?Lg+ZtuqP+_xf+xG4Gxj8vCd=GZLyMBP>
z!)m>j49%r$a?E~f%s%^X;gnt3v!0!GS~y{HP?oc^^TO1~QzmC0Jb3UR`gq|!X-UbQ
z-~EJI1^gHN5pNafUpj^V*|TSTufG18nzXSZVr`i5OrK{@o;-PC6cFNN+A7f7?PLt=2XmqQ
xoPXH-WMzw7#L(TLn2C?^K)}k^GX;%
zz_}5!+3V~EA+*2(AnlS4(0+b^$8*!s3PYyOwc
z#!GfQGt@d*nplLHHzzOZw07#zKKbU4cv|D^n?K|?%yF50bH;{QM-mi_mnbPpYP!ZP
zH*wyw)p#HKcHCv@Wz{~3@8JKz(-FG*Dt}*J-@5h>1`}3?XkBmQR9LmO
zZu?Jvc1NvEGo5|*$fHM#KGoXSR#g008T4xF#EBF0qt;&2J-un$)@%MQ
zOEOzJjl5P$pG^5wD8O>@?%mkc7c-93+>hUo`}^gwV{Kda?D>;WTKe_bix)5Qr=^A-
z$~RN3sgpt*3?}x5)wN!M7YjBd;VO$uebMa
zPUJQI1G^ZvG`2h3+4eR~Y2t~iufMLV+AC*kX(`BX{xgfhT)+K6dee9v5VY!a>0QR9S6Du56YP81TVYd|H|yEX%vt(X)z!W8=FRh1-sPgS(D(A5
zIdkUN%$+^Ec=__>@4HXLK5%EY5Sv)t>hv)5c;TJLk019J@0`Q<;CCI%0TW+a6O)p{
zva+;_dD8_ZmM&nG5c>5%cESD-t-CfB78}yj(oSh>Ykz+H_;I~O-{&O}I(+FyGoN#F
zbH97@=1sZR%6}*`x~@7BtFdt>(DQU2})ThB48A8@~#RjN7vd_6zQfmiqL-J2VsQ#SGZ^Y_eLJCv2q
zuAZjJwuhgm?WCT|lXcgA6(3-VNr-j%^IvA>HLGP?-(8R5Z+m|5!p8rXye$`*R@~3|
Rxe}DjJzf1=);T3K0RVxhlLr6*
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/scorch_6.png b/src/main/resources/assets/ebwizardry/textures/particle/scorch_6.png
new file mode 100644
index 0000000000000000000000000000000000000000..454b064c5764e47225c752d8cc3aa8859587ce13
GIT binary patch
literal 865
zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s7*pj^6T^MeG;2pW})eH;_
zoCO|{#S9GG!XV7ZFl&wk0|NtliKnkC`y+NfF@6yTzcp113=FcFArU3c`MJ5Nc_j=W
z;9QiNSdyBeP@Y+mq2TW68<3)x%Fe*Rbkx(uF~s6@>10Qb+37OJ>ets@+EMp$?dth+
zb(R_IH=WpdYnt2hgQ8JxoILH)%!k7!+^Z_FJ}X!C;^twqR}0zsTbr65Byw2qIC<(y
z){kE^{vM*4(;sidM&o1syI^gX)>xl|GpYtY9_0!f4MNCqA*iHlZXp_wC)QSFd`n
zdp(cs9OLspCI6XSR37;6-@R{N-QmJH{4Ptf%gfDo?b(x)pOZ7^TGan{7UxXwmq)tX
z$`YQ#(#JS4LZ>V}D@$wN=FOi&wWhv`ij2H?GG$X~S=qPXhQELRW*=C8ppfD4{F;R^
zdi>ID4;kA3{{8ExG_hj;?%lsLs;hrTWM^kD-MI1NSqFuJvXqo3(GQF^Xec$_Vz+r*
zdCz?Egwp&2u*x_^~Y6~^oFDGdL?e&{=Ugz1(m*-?_{@ys*
zYvt|G`Kx~WT&=VJbo(d!hX(cof)_adESRFTMy+Lz1?3_YAfgS
SLtq{#rF**ixvX87WPV~EA+(#ih*$*dwr>$krTU0#1LyZh+2
zOvhD0$}3mSxLML+6)dh+rYz5p)S-R&QvQQ`bK?(03LI?_^^uC5F+s}9)8h}brm>*(
z%0{E7d+ly%z9?D8z5JNTx!8Mmir<~w`<&yvM(A8-qlT^%+gJUX)M0Y``5D6isU2)Z
z2d+GQ`ZV{j!Mf0^%wDUaSZDoLH9Br~kBR93!-BBYdsAHk}If8F)hmp@k27)bD(aZ&nsqHs>e#)vfx
z+e5yx3l_R_y{nk_eP3#1d`@0o-PVm84a4=O%U{XbdZNIh=Sb4VM60=c&x&?V&f6Z{
z=c069db3XLbW~h`O5Ejr;fa-_0;_TKD=C2hWAqUyl^Z#IFqbm7JORviN~S
z26L@^0rLlD@lKaVTQ0w}`Ch-zfTwx#WZ~7f-`-kiYLt%OO_K@}0({pau
z$@IFN^-y^vy^^E-aMtZ_lNT>mUVZ<4blv{{dlL+1gkC*+QM}H7Y0&bOA+K70{;d3H
zqtEwX*E;?K+j7sQZLVLtZr!`k)mP2M#Kqq;#xwuV3AkF`pd_#^L`yy=Ki_|A)Y^u}
z7Hx?VI{NzdH*VhaJbUh3S$J63JytumI>CwgZd`l~!3$*ikLz={9;(!u%EivqcsxBl
zz0ql5!TtaZlUr}Ubw7Xpe7>)rU!9TBLQVxG{?Mxoa!-qP&R={nLrUO!sq(z%cW2C;
zxs#p6c;=ZcnX|q(PIrC6;Bf5F6ozLF=8ave>aM*0+B7ZoF6**}_l?h8mzW+pVZ3OL
o*u-h8?p5CUCHkVnBfsWbe!&_WCZ;JSn?R}G)78&qol`;+0BOdT=>Px#
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/snow_0.png b/src/main/resources/assets/ebwizardry/textures/particle/snow_0.png
new file mode 100644
index 0000000000000000000000000000000000000000..53ed7b630ce95cdff80e074c99115bc77c646b83
GIT binary patch
literal 140
zcmeAS@N?(olHy`uVBq!ia0y~yU|<1Z4mJh`hLs=Z)iE$IuqAoByD}*Zs1B{WjH#E|D)Pnuj>p93=E#GelF{r5}E*$2q=00
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/snow_1.png b/src/main/resources/assets/ebwizardry/textures/particle/snow_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..6d792d6d11ca3f2695fac0ac7f7baa3356611d33
GIT binary patch
literal 140
zcmeAS@N?(olHy`uVBq!ia0y~yU|<1Z4mJh`hLs=Z)iE$IuqAoByD
mY;0_75@#DGH!F4UFqC~4ek-#t^)Lei1B0ilpUXO@geCxB;U_Nu
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/snow_2.png b/src/main/resources/assets/ebwizardry/textures/particle/snow_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..6e8d60a12d4b46464df380662a03d95ff80eec29
GIT binary patch
literal 145
zcmeAS@N?(olHy`uVBq!ia0y~yU|<1Z4mJh`hLs=Z)iE$IuqAoByD@~
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/snow_3.png b/src/main/resources/assets/ebwizardry/textures/particle/snow_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..3f6a9c9103abc094a04fe70802c66ac51a0f2892
GIT binary patch
literal 137
zcmeAS@N?(olHy`uVBq!ia0y~yU|<1Z4mJh`hLs=Z)iE$IuqAoByDT+!%>MJ1_w_U#}JFtZ~F|n
z7z{X=KmXVNx#M-vLC4#U?))tR9z80Y4&v8mPXEL$puru@?Y7~=!O~~8heHoA?BBFu
dYeJ-nZ^*-j6=~VGIlm44$rjF6*2UngE?=I0FCx
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_0.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_0.png
new file mode 100644
index 0000000000000000000000000000000000000000..be4ee4f11107d010071c09dfe0014fe6c19ca9fa
GIT binary patch
literal 307
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7Bet#3xhBt!>ljI`2LO03X05+b7YiS_iQ_?P})iUwNWK%_^Z10HCadw|zi(NM7f(4bP0
Hl+XkK;qH7$
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_1.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..5264ba887f361713f4fa199c8fd97a7014e2f32f
GIT binary patch
literal 239
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7Bet#3xhBt!>llx@8
g|NraT961;w&M^OV-v6$Vfq{X+)78&qol`;+0Oh+RNdN!<
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_2.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..8db620f5c545f695dbb711fd1f0d591160564427
GIT binary patch
literal 240
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7Bet#3xhBt!>lJ<=R3>8dCJvQooglr^e4!@YWns)>I-YBx~=DrjB}o8(^j35c)V>V!=1fV?`KHv
zEx)t(hp!t;_S#jeqOwC>44&7Rr=-m-K6Qq{!1$cy)S0XWD_3o~mhztWz`fbmX02FN
oWB4x4Tutep*@?^D?t2-YW&6H9nR5Cs0|Nttr>mdKI;Vst0D+%b$N&HU
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_3.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..dcad491026950949fcfa231909b87b177548aa79
GIT binary patch
literal 215
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7Bet#3xhBt!>lS`MteH0%5(wzHmm;bW}i;4*@E*?VhJPO8)1?8pN8Q<(>+>v(p?$&FE
z?wYzWC^>~L)el|TaiQAUcxFJTrg8k?)HH^Y?Q@G~$fuo)?~czqawB|BSiQ3z0|Ntt
Mr>mdKI;Vst0IGOJKmY&$
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_4.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_4.png
new file mode 100644
index 0000000000000000000000000000000000000000..9f2104b40d4016109dfc5474dac51b71ab54ced9
GIT binary patch
literal 298
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7Bet#3xhBt!>lvbeS
z#P$5?BZp=>ZP^qcG{f$U-kLj;qzlB;7;mjOnvk0QJx*2Zuz0efnAX3ACm(FR*kG`H
z_nqR0hx8{!xUvOY-+F7?(Ys%#vnwxcQMnU4>B&2I<@IZLESm`@10LA*{gs5vEJP!|4Tmln*qBRC{!3cUHx3vIVCg!02dT>zyJUM
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_5.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_5.png
new file mode 100644
index 0000000000000000000000000000000000000000..9783e6579a41ec9dbe5bdbb74e787db21491be55
GIT binary patch
literal 243
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7Bet#3xhBt!>lEak7ae3((L$1RH
z0xlQ#?`!6G74r0)X0zXfyz?99Ix0ABU=2+7$TVx^Tw?O%YCYSz6PCMIF)dj2WX|7@
zQ4BK}oH&G%OUl1XEN&NQskOg$|5E*(*JswAJAU}{-i51XNHU}yOI;Up+bg>_Gdk>;
r#Jy^9!HM^F_ZaS(;^fu&zm{Qjh4)G+9`^SP3=9mOu6{1-oD!M<{n}Zu
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_6.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_6.png
new file mode 100644
index 0000000000000000000000000000000000000000..985abad9b3f3b1f30b61af0c918e354d43ca32eb
GIT binary patch
literal 182
zcmeAS@N?(olHy`uVBq!ia0y~yVBi2@4mJh`h9ms@x)~T4*pj^6T^Rm@;DWu&Co?cG
za29w(7Bet#3xhBt!>lEak7aXC3bfmJ7N
z&kuXQlilL_|Nesjh;e+Cuw;TM=gpRF%GD1a=@=Y~bM!mr?LFlEak7ad~a;Zr+9f
z9_C!OQ$=eIvCY)T)JSAZvyjqoSnv2q>+~o0UruSCzAcMp=;C0E+7|kGqy6kqR)lEak7ad~gABUe*^
z2*dNtvX*UC^ZG8ly|aaHSHpuvt^vPS{Aire$(Gc0_5VJzs@62yGaSmRx;hvF_@+%S
z7O6dbM#5R5EhpTN{cn*>)g=GZccmjrbmK%^OU?!9*WTSP{p@w`y(5XUW(7}FzMQ0!
zIVaX-jdJx94}k~1PP3M2DLqoR);$-V^YzFy(fSAMR!7`76#u>kax8lEak7aXC3bfhEmu
z@97O6uLjTgyS-j2Pf4-r{o~r-x{{H-{l`IZu
dds;Iv>};3oVsYr2!N9=4;OXk;vd$@?2>=#3IF$eZ
literal 0
HcmV?d00001
diff --git a/src/main/resources/assets/ebwizardry/textures/particle/sparkle_particles.png b/src/main/resources/assets/ebwizardry/textures/particle/sparkle_particles.png
deleted file mode 100644
index d767eac39142bcb67c04a86c38c0292df9c01e48..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 917
zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}Y)RhkE)2UEx*7DJwkCaI
zU|`@Z@Q5sCVBi)8VMc~ob0ioT7}!fZeO=ifvPz2cu`=(SDaOFStmNt97!q;#?bNgW
z!hs@3w(h=?PR)?eVf!(c|fMe7uZ1cISqRE3A{Z{1JU;@KL_t@gZLCIh>u^id}t%
zM_6aO37xeO?|PVQrE8ZU(3-=|bMN=={C=jA`TqBVX9{H4
zr=@OuZ1KT+wM1-;L&O=L)0<|@+&K5ppR!d)g&88I9X**csq3gx_AIxVK5ggk@9@)q
z_9>%V&f)Rwat4Oj>ycib3>R+R?5wcqi>fIvH*b~C)1L3Olz~C;c;SMC%O-(3VwN*~
zF10@l|FE)W^~Pk;8z#OlcAaCmaPJ=9{qKR@;j>ruZU6MDN`-?d%z$BqYm-7kZl>h6
z+|5m)vDZtt<<5Tm(W2}ThkOHuJ0h
z%72(!$=ZJX^n{5RGp{*