This is the newest version and it includes "particle flurries" such as:
http://i.imgur.com/XX8tsQP.gif
Credits go to Avatar Realms as well as others including myself for it's development.
In model.java you'll want to add a new vertex point
verticesParticle = new int[numVertices]
Then in each Model constructor you have to add it above each vertex calculation (X,Y,Z)
If you want me to install it for you then it won't be free.
In method483:
Code:
for (int m = 0; m < anInt1626; m++) { int n = m;
int pid = verticesParticle[n]-1;
if (pid < 0)
continue;
//n = 150;
ParticleDefinition def = ParticleDefinition.cache[pid];
int pX = anIntArray1627[n];
int pY = anIntArray1628[n];
int pZ = anIntArray1629[n];
int pZbuffer = vertexPerspectiveZB[n];
if (lrr != 0) {
int sine = Model.modelIntArray1[lrr];
int cosine = Model.modelIntArray2[lrr];
int rotatedX = pZ * sine + pX * cosine >> 16;
pZ = pZ * cosine - pX * sine >> 16;
pX = rotatedX;
}
pX += offX;
pZ += offZ;
Vector basePos = new Vector(pX, -pY, pZ);
for (int p = 0; p < def.getSpawnRate(); p++) {
Particle particle = new Particle(def, basePos, pZbuffer, pid);
Client.getSingleton().addParticle(particle);
}
}
}
Code:
public Model(int modelId) { byte[] is = aClass21Array1661[modelId].aByteArray368;
if (is[is.length - 1] == -1 && is[is.length - 2] == -1)
read622Model(is, modelId);
else
readOldModel(modelId);
int[][] attachments = ParticleAttachment.getAttachments(modelId);
if (attachments != null) {
for (int n = 0; n < attachments.length; n++) {
int[] attach = attachments[n];
if (attach[0] == -1) {
for (int z = 0; z < anIntArray1631.length; z++)
verticesParticle[anIntArray1631[z]] = attach[1] + 1;
} else if (attach[0] == -2) {
for (int z = 0; z < anIntArray1632.length; z++)
verticesParticle[anIntArray1632[z]] = attach[1] + 1;
} else if (attach[0] == -3) {
for (int z = 0; z < anIntArray1633.length; z++)
verticesParticle[anIntArray1633[z]] = attach[1] + 1;
} else if (attach[0] == -4) {
for (int z = 0; z < anIntArray1631.length; z++)
verticesParticle[anIntArray1631[z]] = attach[1] + 1;
for (int z = 0; z < anIntArray1632.length; z++)
verticesParticle[anIntArray1632[z]] = attach[1] + 1;
for (int z = 0; z < anIntArray1633.length; z++)
verticesParticle[anIntArray1633[z]] = attach[1] + 1;
} else {
verticesParticle[attach[0]] = attach[1] + 1;
//System.out.println("Attached " + attach[1] + " to " + attach[0]);
}
}
} ....
Code:
public class Particle {
private int zBuffer;
private int age = 0;
private int color;
private float size;
private Vector velocity;
private float alpha;
public float getAlpha() {
return alpha;
}
public void setAlpha(float alpha) {
this.alpha = alpha;
}
public boolean isDead() {
return dead;
}
private boolean dead = false;
public void tick() {
if (definition == null) return;
age++;
if (age >= definition.getLifespan()) {
dead = true;
return;
}
color += definition.getColorStep();
size += definition.getSizeStep();
position.addLocal(velocity);
velocity.addLocal(definition.getVelocityStep());
alpha += definition.getAlphaStep();
}
public ParticleDefinition getDefinition() {
return definition;
}
private ParticleDefinition definition = null;
public Vector getPosition() {
return position;
}
public void setPosition(Vector position) {
this.position = position;
}
private Vector position;
public Particle(ParticleDefinition pd, Vector position, int zbuffer, int definitionID) {
this(pd.getStartColor(), pd.getStartSize(), pd.getStartVelocity(definitionID).clone(), pd.getSpawnShape().getPoint(ParticleDefinition.RANDOM).addLocal(position), pd.getStartAlpha(), zbuffer);
this.definition = pd;
}
public Particle(int color, float size, Vector velocity, Vector position, float alpha, int zBuffer) {
this.color = color;
this.size = size;
this.velocity = velocity;
this.position = position;
this.alpha = alpha;
this.zBuffer = zBuffer;
}
public int getAge() {
return age;
}
public int getZbuffer() {
return zBuffer;
}
public void setZbuffer(int zBuffer){
this.zBuffer = zBuffer;
}
public void setAge(int age) {
this.age = age;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public float getSize() {
return size;
}
public void setSize(float size) {
this.size = size;
}
public Vector getVelocity() {
return velocity;
}
public void setVelocity(Vector velocity) {
this.velocity = velocity;
}
}
Code:
import java.util.HashMap;
import java.util.Map;
public class ParticleAttachment {
private static final Map<Integer, int[][]> attachments = new HashMap<>();
public static int[][] getAttachments(int model) {
return attachments.get(model);
}
static {
/* Completionist Cape */
attachments.put(65295, new int[][] {{494, 3}, {488 , 3}, {485 , 3}, {476 , 3}, {482 , 3}, {479 , 3}, {491 , 3},});
attachments.put(65328, new int[][] {{494, 3}, {488 , 3}, {485 , 3}, {476 , 3}, {482 , 3}, {479 , 3}, {491 , 3},});
}
}
Code:
import java.util.Random;
public class ParticleDefinition {
public static final Random RANDOM = new Random(System.currentTimeMillis());
public static ParticleDefinition[] cache = new ParticleDefinition[]{
new ParticleDefinition() {
{ // Respected Donator's Cape
setStartVelocity(new Vector(0, -1, 0));
setEndVelocity(new Vector(0, -1, 0));
setGravity(new Vector(0, 1 / 2, 0));
setLifespan(19);
setStartAlpha(0.500f);
setSpawnRate(3);
setSprite(new Sprite("particle 1"));
updateSteps();
}
},
new ParticleDefinition() {
{ // Tok-Haar Kal
setStartVelocity(new Vector(0, -3, 0)); // x z y
setEndVelocity(new Vector(0, -3, 0));
setGravity(new Vector(0, 1 / 2, 0));
setLifespan(19);
setStartColor(0xFF0800);
setSpawnRate(1);
setStartSize(1f);
setEndSize(0);
setStartAlpha(0.075f);
updateSteps();
setColorStep(0x000900);
}
},
new ParticleDefinition() {
{ // Master Dungeoneering Cape
setStartVelocity(new Vector(0, -1, 0));
setEndVelocity(new Vector(0, -1, 0));
setGravity(new Vector(0, 2 / 4, 0));
setLifespan(19);
setStartColor(0x000000);
setSpawnRate(3);
setStartSize(1f);
setEndSize(0.05f);
setStartAlpha(0.015f);
updateSteps();
setColorStep(0x000000);
}
},
new ParticleDefinition() {
{ // Completionist Cape
setStartVelocity(new Vector(0, -3, 0));
setEndVelocity(new Vector(0, -3, 0));
setGravity(new Vector(0, 2 / 4, 0));
setLifespan(19);
setStartColor(0xFFFFFF);
setSpawnRate(4);
setStartSize(0.75f);
setEndSize(0);
setStartAlpha(0.035f);
updateSteps();
setColorStep(0x000000);
}
},
new ParticleDefinition() {
{ // wyrm
setStartVelocity(new Vector(0, 2, 0));
setEndVelocity(new Vector(0, 2, 0));
setGravity(new Vector(0, 33 / 2, 0));
setLifespan(19);
setStartColor(0x000000);
setSpawnRate(3);
setStartSize(0.7f);
setEndSize(0.5f);
setStartAlpha(0f);
setEndAlpha(0.035f);
updateSteps();
setColorStep(0x000000);
}
},
new ParticleDefinition() {
{ // wyrm
setStartVelocity(new Vector(0, 2, 0));
setEndVelocity(new Vector(0, 2, 0));
setGravity(new Vector(0, 3 / 2, 0));
setLifespan(19);
setStartColor(0xFF0800);
setSpawnRate(4);
setStartSize(2f);
setEndSize(0.5f);
setStartAlpha(0f);
setEndAlpha(0.045f);
updateSteps();
setColorStep(0x000900);
}
},
new ParticleDefinition() {
{ // red flaming skull
setStartVelocity(new Vector(0, 2, 0));
setEndVelocity(new Vector(0, 2, 0));
setGravity(new Vector(0, 3 / 2, 0));
setLifespan(15);
setStartColor(0xFF0800);
setSpawnRate(3);
setStartSize(2f);
setEndSize(0.5f);
setStartAlpha(0f);
setEndAlpha(0.065f);
updateSteps();
setColorStep(0x000900);
}
},
new ParticleDefinition() {
{ // Respected Donator's Cape
setStartVelocity(new Vector(0, 2, 0));
setEndVelocity(new Vector(0, 2, 0));
setGravity(new Vector(0, 1 / 2, 0));
setLifespan(15);
setStartAlpha(0.035f);
setEndAlpha(0.000f);
setSpawnRate(1);
setStartSize(0.2f);
setSprite(new Sprite("particle 2"));
updateSteps();
}
},
new ParticleDefinition() {
{ // blue flaming skull
setStartVelocity(new Vector(0, 2, 0));
setEndVelocity(new Vector(0, 2, 0));
setGravity(new Vector(0, 3 / 2, 0));
setLifespan(15);
setStartColor(0x0052cc);
setSpawnRate(3);
setStartSize(2f);
setEndSize(0.5f);
setStartAlpha(0f);
setEndAlpha(0.065f);
updateSteps();
setColorStep(0x000900);
}
},
new ParticleDefinition() {
{ // Respected Donator's Cape
setStartVelocity(new Vector(0, 2, 0));
setEndVelocity(new Vector(0, 2, 0));
setGravity(new Vector(0, 1 / 2, 0));
setLifespan(15);
setStartAlpha(0.035f);
setEndAlpha(0.000f);
setSpawnRate(1);
setStartSize(0.2f);
setSprite(new Sprite("particle 3"));
updateSteps();
}
},};
/**
* The size at which the particle starts.
*/
private float startSize = 1f;
/**
* The size at which the particle is at the end of it's life.
*/
private float endSize = 1f;
/**
* The start color of the particles.
*/
private int startColor = 0xFFFFFFFF;
/**
* The end color of the particles.
*/
private int endColor = 0xFFFFFFFF;
/**
* The velocity when the particle is first spawned.
*/
private Vector startVelocity = Vector.ZERO;
/**
* The velocity of the particle when it dies.
*/
private Vector endVelocity = Vector.ZERO;
/**
* The amount of frames a particle survives for.
*/
private int lifespan = 1;
/**
* The maximum amount of particles at any given moment.
*/
private static int maxParticles = 10000;
/**
* The amount of particles spawned each frame.
*/
private int spawnRate = 1;
/**
* The sprite of the particles.
*/
private int zBuffer;
private Sprite sprite;
private float startAlpha = 1f;
private float endAlpha = 0.05f;
public Vector getGravity() {
return gravity;
}
public void setGravity(Vector gravity) {
this.gravity = gravity;
}
public int getzBuffer() {
return zBuffer;
}
public void setzBuffer(int zBuffer) {
this.zBuffer = zBuffer;
}
/**
* The gravitational force for this object.
*/
private Vector gravity;
public float getStartAlpha() {
return startAlpha;
}
public void setStartAlpha(float startAlpha) {
this.startAlpha = startAlpha;
}
public float getEndAlpha() {
return endAlpha;
}
public void setEndAlpha(float endAlpha) {
this.endAlpha = endAlpha;
}
public float getAlphaStep() {
return alphaStep;
}
public void setAlphaStep(float alphaStep) {
this.alphaStep = alphaStep;
}
public Sprite getSprite() {
return sprite;
}
public void setSprite(Sprite sprite) {
this.sprite = sprite;
}
public SpawnShape getSpawnShape() {
return spawnShape;
}
public void setSpawnShape(SpawnShape spawnShape) {
this.spawnShape = spawnShape;
}
public int randomWithRange(int min, int max) {
int range = (max - min) + 1;
return (int) (Math.random() * range) + min;
}
/**
* The shape which defines the potential origins for particle spawns.
*/
private SpawnShape spawnShape = new PointSpawnShape(Vector.ZERO);
public int getSpawnRate() {
return spawnRate;
}
public void setSpawnRate(int spawnRate) {
this.spawnRate = spawnRate;
}
public static int getMaxParticles() {
return maxParticles;
}
public void setMaxParticles(int maxParticles) {
this.maxParticles = maxParticles;
}
public float getStartSize() {
return startSize;
}
public void setStartSize(float startSize) {
this.startSize = startSize;
}
public float getEndSize() {
return endSize;
}
public void setEndSize(float endSize) {
this.endSize = endSize;
}
public int getStartColor() {
return startColor;
}
public void setStartColor(int startColor) {
this.startColor = startColor;
}
public int getEndColor() {
return endColor;
}
public void setEndColor(int endColor) {
this.endColor = endColor;
}
public Vector getStartVelocity(int id) {
switch (id) {
default:
return new Vector(this.startVelocity.getX() + randomWithRange(-3, 3), this.startVelocity.getY() + randomWithRange(0, 9), this.startVelocity.getZ() + randomWithRange(-3, 3));
}
}
public void setStartVelocity(Vector startVelocity) {
this.startVelocity = startVelocity;
}
public Vector getEndVelocity() {
return endVelocity;
}
public void setEndVelocity(Vector endVelocity) {
this.endVelocity = endVelocity;
}
public int getLifespan() {
return lifespan;
}
public void setLifespan(int lifespan) {
this.lifespan = lifespan;
}
private Vector velocityStep;
private int colorStep;
public void setVelocityStep(Vector velocityStep) {
this.velocityStep = velocityStep;
}
public void setColorStep(int colorStep) {
this.colorStep = colorStep;
}
public void setSizeStep(float sizeStep) {
this.sizeStep = sizeStep;
}
public float getSizeStep() {
return sizeStep;
}
public Vector getVelocityStep() {
return velocityStep;
}
public int getColorStep() {
return colorStep;
}
private float sizeStep;
private float alphaStep;
public void updateSteps() {
this.sizeStep = (endSize - startSize) / (lifespan * 1f);
this.colorStep = (endColor - startColor) / lifespan;
this.velocityStep = endVelocity.subtract(startVelocity).divide(lifespan);
this.alphaStep = (endAlpha - startAlpha) / lifespan;
}
public void updateStepsNoAlpha() {
this.sizeStep = (endSize - startSize) / (lifespan * 1f);
this.colorStep = (endColor - startColor) / lifespan;
this.velocityStep = endVelocity.subtract(startVelocity).divide(lifespan);
//this.alphaStep = (endAlpha - startAlpha) / lifespan;
}
}
Code:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ParticleSystem {
private ParticleDefinition definition;
private List<Particle> currentParticles;
private Random random;
private Vector velocityStep;
private int colorStep;
private float sizeStep;
private Vector position;
public ParticleSystem(ParticleDefinition definition) {
this.definition = definition;
this.currentParticles = new ArrayList<Particle>(definition.getMaxParticles());
this.random = new Random(System.currentTimeMillis());
this.sizeStep = (definition.getEndSize() - definition.getStartSize()) / definition.getLifespan();
this.colorStep = (definition.getEndColor() - definition.getStartColor()) / definition.getLifespan();
this.velocityStep = definition.getEndVelocity().subtract(definition.getStartVelocity(0)).divide(definition.getLifespan());
}
public void tick() {
List<Particle> deadParticles = new ArrayList<Particle>();
for (Particle p : currentParticles) {
if (p == null) continue;
if (p.getAge() == definition.getLifespan()) {
deadParticles.add(p);
continue;
}
p.setAge(p.getAge() + 1);
p.setColor(p.getColor() + colorStep);
p.setSize(p.getSize() + sizeStep);
p.getPosition().addLocal(p.getVelocity());
p.getVelocity().addLocal(velocityStep);
if (definition.getGravity() != null) {
p.getPosition().addLocal(definition.getGravity());
}
}
currentParticles.removeAll(deadParticles);
if (currentParticles.size() < definition.getMaxParticles()) {
for (int i = 0; i < definition.getSpawnRate(); i++) {
// Create the particle.
Particle p = new Particle(definition.getStartColor(), definition.getStartSize(), definition.getStartVelocity(0).clone(), definition.getSpawnShape().getPoint(random).addLocal(position), definition.getStartAlpha(), definition.getzBuffer());
currentParticles.add(p);
}
}
}
public void render() {
tick();
Client c = Client.getSingleton();
boolean spriteMode = getDefinition().getSprite() != null;
for (Particle p : getCurrentParticles()) {
int i = p.getPosition().getX();
int j = p.getPosition().getY();
int k = p.getPosition().getZ();
c.calcEntityScreenPos(i, j, k);
//ps.getDefinition().getSprite().drawCenteredImage(l1, i2);
float alpha = 1f - (p.getAge() / (getDefinition().getLifespan() * 1f));
int alphaI = (int)(alpha * 255);
if (spriteMode)
getDefinition().getSprite().drawAdvancedSprite(c.spriteDrawX, c.spriteDrawY, alphaI);
else {
DrawingArea.drawFilledCircle(c.spriteDrawX, c.spriteDrawY, (int)(p.getSize() * 4), p.getColor(), alphaI);
}
}
}
public Vector getPosition() {
return position;
}
public void setPosition(Vector position) {
this.position = position;
}
public List<Particle> getCurrentParticles() {
return currentParticles;
}
public ParticleDefinition getDefinition() {
return definition;
}
}
Code:
public class Vector {
public static final Vector ZERO = new Vector(0, 0, 0);
private int x;
private int y;
private int z;
public Vector(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getZ() {
return z;
}
public Vector subtract(Vector other) {
return new Vector(this.x - other.x, this.y - other.y, this.z - other.z);
}
public Vector divide(float scalar) {
return new Vector((int)(this.x / scalar), (int)(this.y / scalar), (int)(this.z / scalar));
}
public Vector addLocal(Vector other) {
this.x += other.x;
this.y += other.y;
this.z += other.z;
return this;
}
public Vector mix(Vector other, float x, float y, float z) {
return new Vector(this.x + (int)(other.x * x), this.y + (int)(other.y * y), this.z + (int)(other.z * z));
}
@Override
public Vector clone() {
return new Vector(this.x, this.y, this.z);
}
public int randomWithRange(int min, int max)
{
int range = (max - min) + 1;
return (int)(Math.random() * range) + min;
}
@Override
public String toString() {
return "Vector{" +
"x=" + x +
", y=" + y +
", z=" + z +
'}';
}
}