Latest Update: May 22, 2011 - Added multiple attack animations support.
Most servers use switch statements that become really large and unnecessary to find an NPCs attack, block, and death animation. I have now written a cache reader/writer/editor to store and change all of this data. This editor comes with a .dat file that contains an NPC list up to 602 NPCs. Not all animations have been added for each NPC!
This tool allows you to edit the attack, block, and death animations of an NPC. If you want to add multiple attack, simply separate each ID with a comma(space or no space, doesn't matter). When you're done editing, simply hit "Build Cache". By default, NPCs will have human animation IDs. This editor shows each NPCs standAnimation and walkAnimation ID, so you can find the other animation IDs based on those. Stand and walk animations are uneditable so you don't accidentally screw up .
Download the NPC Animation Editor!
Here is the reader. You have to import your own Stream class, etcetera Also, you must replace "REPLACE PATH HERE" with your chosen location. But, this will read it and such:
Code:
package server.model.npcs;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import galkon.server.util.Stream;
import galkon.server.util.Misc;
public class NPCAnimation {
public static String cacheLocation = "REPLACE PATH HERE";
public static void readCache() {
Stream stream = new Stream(readFile(cacheLocation));
totalNPCs = stream.readShort();
if(cache == null)
cache = new NPCAnimation[totalNPCs];
for(int j = 0; j < totalNPCs; j++) {
if(cache[j] == null)
cache[j] = new NPCAnimation();
cache[j].readValues(stream);
}
}
public static byte[] readFile(String name) {
try {
RandomAccessFile raf = new RandomAccessFile(name, "r");
ByteBuffer buf = raf.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, raf.length());
try {
if (buf.hasArray()) {
return buf.array();
} else {
byte[] array = new byte[buf.remaining()];
buf.get(array);
return array;
}
} finally {
raf.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void readValues(Stream stream) {
do {
int var = stream.readUByte();
if(var == 0)
return;
if(var == 1) {
name = stream.readString();
} else if(var == 2) {
standAnimation = stream.readInt();
} else if(var == 3) {
walkAnimation = stream.readInt();
} else if(var == 4) {
attackAnimations = stream.readString();
if (attackAnimations == null) {
attackAnimations = Integer.toString(HUMAN_ATTACK);
}
} else if(var == 5) {
blockAnimation = stream.readInt();
} else if(var == 6) {
deathAnimation = stream.readInt();
} else {
}
} while(true);
}
public static int getAttackAnimation(int npcID) {
String[] animationString = cache[npcID].attackAnimations.split(",");
int[] animationIndex = new int[animationString.length];
for (int index = 0; index < animationString.length; index++) {
animationIndex[index] = Integer.parseInt(animationString[index]);
}
return animationString.length > 1 ? animationIndex[Misc.random(animationIndex.length) - 1] : animationIndex[0];
}
public void setDefaults() {
name = "null";
standAnimation = HUMAN_STAND;
walkAnimation = 808;
attackAnimation = HUMAN_ATTACK;
blockAnimation = HUMAN_BLOCK;
deathAnimation = HUMAN_DEATH;
}
public NPCAnimation() {
}
public static NPCAnimation cache[];
public static int npcs;
public static int totalNPCs;
public String name;
public int standAnimation;
public int walkAnimation;
public String attackAnimations;
public int attackAnimation;
public int blockAnimation;
public int deathAnimation;
public final static int HUMAN_STAND = 808;
public final static int HUMAN_ATTACK = 806;
public final static int HUMAN_BLOCK = 404;
public final static int HUMAN_DEATH = 2304;
}
Also;
Code:
readShort() = readUnsignedWord()
readUByte() = readUnsignedByte()
Implementation and usage
You can read the cache on startup by simply calling 'NPCAnimation.readCache();" on startup (most likely in Server.java). Then you can use things like:
Code:
int attackAnimation = NPCAnimation.getAttackAnimation(NPCHandler.npcs[i].id);
int blockAnimation = NPCAnimation.cache[NPCHandler.npcs[i].id].blockAnimation;
int deathAnimation = NPCAnimation.cache[NPCHandler.npcs[i].id].deathAnimation;
or whatever it is in your server.
Multiple animation support has been added and it automatically uses a random animation when you use "NPCAnimation.getAttackAnimation(NPCID);".