Index: main/Creature.java
===================================================================
--- main/Creature.java	(revision 08704682fb409c42246c2544c64a8681a3fd9734)
+++ main/Creature.java	(revision 8edd04e287f45041eeee2cb294847453e4c6aac4)
@@ -1,220 +1,765 @@
 package main;
 
-import java.awt.image.*;
-
-public class Creature {
-	private String name;
-	private CreatureType type;
-	private BufferedImage img;
-	private Gender gender;
-	private int level;
-	private Point loc;
-	private int speed;
-	private long lastMoved;
-	private int attackSpeed;
-	private int damage;
-	private long lastAttacked;
-	private int strength;
-	private int dexterity;
-	private int constitution;
-	private int charisma;
-	private int wisdom;
-	private int intelligence;
-	private int hitpoints;
-	private int manapoints;
-	private int maxHitpoints;
-	private int maxManapoints;
-	
-	public Creature() {
-		name = "";
-		gender = Gender.None;
-		loc = new Point(0, 0);
-	}
-
-	public Creature(String name) {
-		this.name = name;
-		loc = new Point(0, 0);
-	}
-	
-	public Creature(String name, Gender gender) {
-		this.name = name;
-		this.gender = gender;
-		loc = new Point(0, 0);
-	}
-	
-	public int getAttackSpeed() {
-		return attackSpeed;
-	}
-
-	public int getCharisma() {
-		return charisma;
-	}
-
-	public int getConstitution() {
-		return constitution;
-	}
-
-	public int getDamage() {
-		return damage;
-	}
-
-	public int getDexterity() {
-		return dexterity;
-	}
-
-	public Gender getGender() {
-		return gender;
-	}
-
-	public int getHitpoints() {
-		return hitpoints;
-	}
-	
-	public BufferedImage getImg() {
-		return img;
-	}
-
-	public int getIntelligence() {
-		return intelligence;
-	}
-
-	public long getLastAttacked() {
-		return lastAttacked;
-	}
-
-	public long getLastMoved() {
-		return lastMoved;
-	}
-
-	public int getLevel() {
-		return level;
-	}
-
-	public Point getLoc() {
-		return loc;
-	}
-
-	public int getManapoints() {
-		return manapoints;
-	}
-
-	public int getMaxHitpoints() {
-		return maxHitpoints;
-	}
-
-	public int getMaxManapoints() {
-		return maxManapoints;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public int getSpeed() {
-		return speed;
-	}
-
-	public int getStrength() {
-		return strength;
-	}
-	
-	public CreatureType getType() {
-		return type;
-	}
-
-	public int getWisdom() {
-		return wisdom;
-	}
-
-	public void setAttackSpeed(int attackSpeed) {
-		this.attackSpeed = attackSpeed;
-	}
-
-	public void setCharisma(int charisma) {
-		this.charisma = charisma;
-	}
-
-	public void setConstitution(int constitution) {
-		this.constitution = constitution;
-	}
-
-	public void setDamage(int damage) {
-		this.damage = damage;
-	}
-
-	public void setDexterity(int dexterity) {
-		this.dexterity = dexterity;
-	}
-
-	public void setGender(Gender gender) {
-		this.gender = gender;
-	}
-
-	public void setHitpoints(int hitpoints) {
-		this.hitpoints = hitpoints;
-	}
-	
-	public void setImg(BufferedImage img) {
-		this.img = img;
-	}
- 
-	public void setIntelligence(int intelligence) {
-		this.intelligence = intelligence;
-	}
-
-	public void setLastAttacked(long lastAttacked) {
-		this.lastAttacked = lastAttacked;
-	}
-
-	public void setLastMoved(long lastMoved) {
-		this.lastMoved = lastMoved;
-	}
-
-	public void setLevel(int level) {
-		this.level = level;
-	}
-
-	public void setLoc(Point loc) {
-		this.loc = loc;
-	}
-
-	public void setManapoints(int manapoints) {
-		this.manapoints = manapoints;
-	}
-
-	public void setMaxHitpoints(int maxHitpoints) {
-		this.maxHitpoints = maxHitpoints;
-	}
-
-	public void setMaxManapoints(int maxManapoints) {
-		this.maxManapoints = maxManapoints;
-	}
-
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	public void setSpeed(int speed) {
-		this.speed = speed;
-	}
-
-	public void setStrength(int strength) {
-		this.strength = strength;
-	}
-	
-	public void setType(CreatureType type) {
-		this.type = type;
-	}
-
-	public void setWisdom(int wisdom) {
-		this.wisdom = wisdom;
-	}
-	
-	public String toString() {
-		return name;
-	}
-	
-	public boolean equals(Object c) {
-		return name.trim().equals(((Creature)c).name.trim());
-	}
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.util.*;
+import javax.imageio.ImageIO;
+
+import gamegui.Animation;
+
+public class Creature implements Comparable<Creature> {
+
+  public int passive;
+  public int thorns;
+  public int confused;
+  public int sand;
+
+  protected String name;
+  protected CreatureType type;
+  protected Model model;
+  protected int level;
+  protected Point loc;
+  protected int[] attributes;  
+  protected int hitpoints;
+  protected int manapoints;
+  protected int maxHitpoints;
+  protected int maxManapoints;
+  protected int experience;
+  protected EquippedWeapon weapon;
+  protected EquippedWeapon spell;
+
+  private Point target;
+  private Creature enemyTarget;
+  private int speed;
+  private long lastMoved;
+  private long lastAttacked;
+  private LinkedList<ItemDrop> drops;
+  private LinkedList<EffectTimer> effectTimers;
+  private boolean disabled;
+  private SpawnPoint spawnPoint;
+  private boolean dying;
+
+  public Creature() {
+    this.name = "";
+    this.loc = new Point(0, 0);
+    this.target = this.loc;
+    this.attributes = new int[4];
+    this.experience = 0;
+    this.weapon = null;
+    this.spell = null;
+    this.drops = new LinkedList<ItemDrop>();
+    this.effectTimers = new LinkedList<EffectTimer>();
+    this.disabled = false;
+    this.spawnPoint = null;
+    this.passive = 0;
+    this.thorns = 0;
+    this.confused = 0;
+    this.sand = 0;
+    this.dying = false;
+  }
+
+  public Creature(String name, CreatureType type) {
+    this.name = name;
+    this.type = type;
+    this.loc = new Point(0, 0);
+    this.target = this.loc;
+    this.attributes = new int[4];
+    this.experience = 0;
+    this.weapon = null;
+    this.spell = null;
+    this.drops = new LinkedList<ItemDrop>();
+    this.effectTimers = new LinkedList<EffectTimer>();
+    this.disabled = false;
+    this.spawnPoint = null;
+    this.passive = 0;
+    this.thorns = 0;
+    this.confused = 0;
+    this.sand = 0;
+    this.dying = false;
+  }
+
+  public Creature(Creature cr) {
+    this.name = cr.name;
+    this.type = cr.type;
+    this.model = new Model(cr.model);
+    this.level = cr.level;
+    this.loc = new Point(cr.loc);
+    this.target = cr.target;
+    this.speed = cr.speed;
+    this.lastMoved = cr.lastMoved;
+    this.lastAttacked = cr.lastAttacked;
+    this.attributes = (int[])cr.attributes.clone();
+    this.hitpoints = cr.hitpoints;
+    this.manapoints = cr.manapoints;
+    this.maxHitpoints = cr.maxHitpoints;
+    this.maxManapoints = cr.maxManapoints;
+    this.experience = cr.experience;
+    this.weapon = cr.weapon.copy((Point)null);
+    if (cr.spell != null)
+      this.spell = cr.spell.copy((Point)null); 
+    this.drops = cr.drops;
+    this.effectTimers = new LinkedList<EffectTimer>(cr.effectTimers);
+    this.disabled = cr.disabled;
+    this.spawnPoint = null;
+    this.passive = cr.passive;
+    this.thorns = cr.thorns;
+    this.confused = cr.confused;
+    this.sand = cr.sand;
+    this.dying = cr.dying;
+  }
+
+  public Creature copy() {
+    return new Creature(this);
+  }
+
+  public void setDying(boolean dying) {
+    if (!this.model.hasDeath())
+      return; 
+    if (dying) {
+      this.model.setAction(Action.Dying);
+    } else {
+      this.model.getAnimation(Direction.West, Action.Dying).reset();
+    }
+    this.dying = dying;
+  }
+
+  public boolean isDying() {
+    return this.dying;
+  }
+
+  public void checkTimedEffects() {
+    Iterator<EffectTimer> iter = this.effectTimers.iterator();
+    while (iter.hasNext()) {
+      EffectTimer cur = iter.next();
+      if (cur.expired()) {
+        cur.getEffect().cancelEffect(this);
+        iter.remove();
+      }
+    }
+  }
+
+  public void addEffect(TimedEffect e) {
+    this.effectTimers.add(new EffectTimer(e, e.getDuration()));
+  }
+
+  public Point move() {
+    Point newLoc;
+    double dist = (this.speed * (System.currentTimeMillis() - this.lastMoved) / 1000L);
+    if (this.lastMoved == 0L) {
+      dist = 0.0D;
+    }
+    if (this.enemyTarget != null) {
+      this.target = this.enemyTarget.loc;
+    }
+    this.lastMoved = System.currentTimeMillis();
+    if (Point.dist(this.loc, this.target) <= dist) {
+      newLoc = this.target;
+      if (this.model.getAction() != Action.Attacking) {
+        this.model.setAction(Action.Standing);
+      }
+    } else {
+      if (this.model.getAction() != Action.Attacking) {
+        this.model.setAction(Action.Walking);
+      }
+      int xDif = (int)(Point.xDif(this.loc, this.target) * dist / Point.dist(this.loc, this.target));
+      int yDif = (int)(Point.yDif(this.loc, this.target) * dist / Point.dist(this.loc, this.target));
+      newLoc = new Point(this.loc.getX(), this.loc.getXMin() + xDif, this.loc.getY(), this.loc.getYMin() + yDif);
+      newLoc.setX(newLoc.getX() + newLoc.getXMin() / 100);
+      newLoc.setXMin(newLoc.getXMin() % 100);
+      newLoc.setY(newLoc.getY() + newLoc.getYMin() / 100);
+      newLoc.setYMin(newLoc.getYMin() % 100);
+      if (newLoc.getXMin() < 0) {
+        newLoc.setX(newLoc.getX() - 1);
+        newLoc.setXMin(newLoc.getXMin() + 100);
+      } else if (newLoc.getYMin() < 0) {
+        newLoc.setY(newLoc.getY() - 1);
+        newLoc.setYMin(newLoc.getYMin() + 100);
+      }
+      this.model.setDirection(calcDirection());
+    }
+    return newLoc;
+  }
+
+  private Direction calcDirection() {
+    Direction dir;
+    int xDif2 = Point.xDif(this.loc, this.target);
+    int yDif2 = Point.yDif(this.target, this.loc);
+    double angle = 1.5707963267948966D;
+    if (xDif2 == 0) {
+      if (yDif2 != 0) {
+        angle *= Math.abs(yDif2 / yDif2);
+      }
+    } else {
+      angle = Math.atan(yDif2 / xDif2);
+    }
+    if (angle >= 0.7853981633974483D) {
+      dir = Direction.North;
+    } else if (-0.7853981633974483D <= angle && angle <= 0.7853981633974483D) {
+      dir = Direction.East;
+    } else {
+      dir = Direction.South;
+    }
+    if (xDif2 < 0)
+      switch (dir) {
+        case North:
+          dir = Direction.South;
+          break;
+        case South:
+          dir = Direction.North;
+          break;
+        case East:
+          dir = Direction.West;
+          break;
+      } 
+    return dir;
+  }
+
+  public Projectile attack(Creature enemy, AttackType attType) {
+    Weapon weap = selectWeapon(attType);
+    if (System.currentTimeMillis() - this.lastAttacked >= (weap.getAttackSpeed() * 100) && !this.disabled) {
+      this.lastAttacked = System.currentTimeMillis();
+      Point oldTarget = this.target;
+      this.target = enemy.getLoc();
+      this.model.setDirection(calcDirection());
+      this.target = oldTarget;
+      if (attType != AttackType.Spell) {
+        this.model.setAction(Action.Attacking);
+        this.model.getAnimation(this.model.getDirection(), this.model.getAction()).reset();
+      }
+      if (weap.getType() == ItemType.RangedWeapon || weap.getType() == ItemType.Spell) {
+        Point loc = new Point(this.loc);
+        loc.setY(loc.getY() - 55);
+        return weap.spawnProjectile(loc, enemy.getLoc());
+      }
+      weap.applyContactEffects(enemy);
+    }
+    return null;
+  }
+
+  public Projectile attack(Point targ, AttackType attType) {
+    Weapon weap = selectWeapon(attType);
+    if ((System.currentTimeMillis() - this.lastAttacked) / 100L >= weap.getAttackSpeed() && !this.disabled) {
+      this.lastAttacked = System.currentTimeMillis();
+      Point oldTarget = this.target;
+      this.target = targ;
+      this.model.setDirection(calcDirection());
+      this.target = oldTarget;
+      if (attType != AttackType.Spell) {
+        this.model.setAction(Action.Attacking);
+        this.model.getAnimation(this.model.getDirection(), this.model.getAction()).reset();
+      }
+      if (weap.getType() == ItemType.RangedWeapon || weap.getType() == ItemType.Spell) {
+        Point loc = new Point(this.loc);
+        loc.setY(loc.getY() - 30);
+        return weap.spawnProjectile(loc, targ);
+      }
+    }
+    return null;
+  }
+
+  private Weapon selectWeapon(AttackType attType) {
+    switch (attType) {
+      case Weapon:
+        return this.weapon;
+      case Spell:
+        return this.spell;
+    }
+    return this.weapon;
+  }
+
+  public void addDrop(ItemDrop item) {
+    this.drops.add(item);
+  }
+
+  public LinkedList<ItemDrop> getDrops() {
+    return this.drops;
+  }
+
+  public LinkedList<Item> spawnDrops() {
+    LinkedList<Item> newDrops = new LinkedList<Item>();
+    Iterator<ItemDrop> iter = this.drops.iterator();
+    Random gen = new Random();
+    while (iter.hasNext()) {
+      ItemDrop cur = iter.next();
+      if (gen.nextDouble() <= cur.getDropChance()) {
+        newDrops.add(cur.getItem());
+      }
+    }
+    return newDrops;
+  }
+
+  public void draw(Graphics g, int playerX, int playerY) {
+    if (this.passive > 0) {
+      g.drawImage(LostHavenRPG.passiveAura, 375 + this.loc.getX() - playerX, 300 - this.model.getHeight() + this.loc.getY() - playerY, null);
+    }
+    if (this.thorns > 0) {
+      g.drawImage(LostHavenRPG.thornsAura, 375 + this.loc.getX() - playerX, 300 - this.model.getHeight() + this.loc.getY() - playerY, null);
+    }
+    this.model.draw(g, 400 + this.loc.getX() - playerX, 300 + this.loc.getY() - playerY);
+    if (this.confused > 0) {
+      g.drawImage(LostHavenRPG.confuseAura, 375 + this.loc.getX() - playerX, 300 - this.model.getHeight() + this.loc.getY() - playerY, null);
+    }
+    if (this.sand > 0) {
+      g.drawImage(LostHavenRPG.sandAura, 375 + this.loc.getX() - playerX, 300 - this.model.getHeight() + this.loc.getY() - playerY, null);
+    }
+    g.setColor(Color.red);
+    g.fillRect(360 + this.loc.getX() - playerX, 290 - this.model.getHeight() + this.loc.getY() - playerY, 80 * this.hitpoints / this.maxHitpoints, 10);
+    g.setColor(Color.black);
+    Font font12 = new Font("Arial", 0, 12);
+    FontMetrics metrics = g.getFontMetrics(font12);
+    g.setFont(font12);
+    g.drawString(this.name, 400 + this.loc.getX() - playerX - metrics.stringWidth(this.name) / 2, 300 - this.model.getHeight() + this.loc.getY() - playerY);
+  }
+
+  public void save(PrintWriter out) {
+    out.println(this.type);
+    if (this.spawnPoint == null) {
+      out.println(-1);
+    } else {
+      out.println(this.spawnPoint.idNum);
+    }
+    out.println(String.valueOf(this.loc.getX()) + "," + this.loc.getY());
+    out.println(this.model.getDirection());
+    out.println(this.model.getAction());
+    out.println(this.hitpoints);
+    out.println(this.manapoints);
+    out.println(this.passive);
+    out.println(this.thorns);
+    out.println(this.confused);
+    out.println(this.sand);
+    if (this.weapon == null) {
+      out.println("None");
+    } else {
+      out.println(this.weapon.getName());
+    }
+  }
+
+  public static Creature loadTemplate(BufferedReader in) {
+    Creature cr = new Creature();
+    BufferedImage[] imgProj = new BufferedImage[8];
+    try {
+      cr.name = in.readLine();
+      cr.type = CreatureType.valueOf(cr.name);
+      if (cr.type == CreatureType.Player) {
+        cr = Player.loadTemplate(in);
+      }
+      cr.setSpeed(Integer.parseInt(in.readLine()));
+      cr.setAttribute(Attribute.Strength, Integer.parseInt(in.readLine()));
+      cr.setAttribute(Attribute.Dexterity, Integer.parseInt(in.readLine()));
+      cr.setAttribute(Attribute.Constitution, Integer.parseInt(in.readLine()));
+      cr.setAttribute(Attribute.Wisdom, Integer.parseInt(in.readLine()));
+      ItemType wType = ItemType.valueOf(in.readLine());
+      if (wType == ItemType.RangedWeapon) {
+        imgProj = LostHavenRPG.imgBow;
+      } else if (wType == ItemType.Spell) {
+        imgProj[0] = ImageIO.read(cr.getClass().getResource("../images/" + cr.type.toString() + "/proj.png"));
+        imgProj[1] = ImageIO.read(cr.getClass().getResource("../images/" + cr.type.toString() + "/proj.png"));
+        imgProj[2] = ImageIO.read(cr.getClass().getResource("../images/" + cr.type.toString() + "/proj.png"));
+        imgProj[3] = ImageIO.read(cr.getClass().getResource("../images/" + cr.type.toString() + "/proj.png"));
+        imgProj[4] = ImageIO.read(cr.getClass().getResource("../images/" + cr.type.toString() + "/proj.png"));
+        imgProj[5] = ImageIO.read(cr.getClass().getResource("../images/" + cr.type.toString() + "/proj.png"));
+        imgProj[6] = ImageIO.read(cr.getClass().getResource("../images/" + cr.type.toString() + "/proj.png"));
+        imgProj[7] = ImageIO.read(cr.getClass().getResource("../images/" + cr.type.toString() + "/proj.png"));
+      }
+      cr.model = cr.loadModel(cr.type.toString());
+      cr.setWeapon(new Weapon("None", wType, "Dagger.png", imgProj, 10, Integer.parseInt(in.readLine()), Integer.parseInt(in.readLine())));
+      cr.setExperience(Integer.parseInt(in.readLine()));
+    } catch (IOException ioe) {
+      ioe.printStackTrace();
+    }
+    return cr;
+  }
+
+  public Model loadModel(String folder) {
+    boolean noAnims = false;
+    Animation anmStandN = new Animation("north", 0, 0, 40, 60, 300, true);
+    Animation anmStandS = new Animation("south", 0, 0, 40, 60, 300, true);
+    Animation anmStandE = new Animation("east", 0, 0, 40, 60, 300, true);
+    Animation anmStandW = new Animation("west", 0, 0, 40, 60, 300, true);
+    Animation anmWalkN = new Animation("north", 0, 0, 40, 60, 300, true);
+    Animation anmWalkS = new Animation("south", 0, 0, 40, 60, 300, true);
+    Animation anmWalkE = new Animation("east", 0, 0, 40, 60, 300, true);
+    Animation anmWalkW = new Animation("west", 0, 0, 40, 60, 300, true);
+    Animation anmAttackN = new Animation("north", 0, 0, 40, 60, 500, false);
+    Animation anmAttackS = new Animation("south", 0, 0, 40, 60, 500, false);
+    Animation anmAttackE = new Animation("east", 0, 0, 40, 60, 500, false);
+    Animation anmAttackW = new Animation("west", 0, 0, 40, 60, 500, false);
+    Animation anmDeath = new Animation("west", 0, 0, 40, 60, 1000, false);
+    BufferedImage walkN = null;
+    BufferedImage walkS = null;
+    BufferedImage walkE = null;
+    BufferedImage walkW = null;
+    boolean hasDeathAnim = (getClass().getResource("../images/" + folder + "/Death1.png") != null);
+    try {
+      if (getClass().getResource("../images/" + folder + "/WalkN.png") != null) {
+        walkN = ImageIO.read(getClass().getResource("../images/" + folder + "/WalkN.png"));
+        anmWalkN.addFrame(walkN);
+        walkS = ImageIO.read(getClass().getResource("../images/" + folder + "/WalkS.png"));
+        anmWalkS.addFrame(walkS);
+        walkE = ImageIO.read(getClass().getResource("../images/" + folder + "/WalkE.png"));
+        anmWalkE.addFrame(walkE);
+        walkW = ImageIO.read(getClass().getResource("../images/" + folder + "/WalkW.png"));
+        anmWalkW.addFrame(walkW);
+      } else if (getClass().getResource("../images/" + folder + "/WalkN1.png") != null) {
+        walkN = ImageIO.read(getClass().getResource("../images/" + folder + "/WalkN1.png"));
+        anmWalkN.addFrame(walkN);
+        anmWalkN.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/WalkN2.png")));
+        walkS = ImageIO.read(getClass().getResource("../images/" + folder + "/WalkS1.png"));
+        anmWalkS.addFrame(walkS);
+        anmWalkS.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/WalkS2.png")));
+        walkE = ImageIO.read(getClass().getResource("../images/" + folder + "/WalkE1.png"));
+        anmWalkE.addFrame(walkE);
+        anmWalkE.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/WalkE2.png")));
+        walkW = ImageIO.read(getClass().getResource("../images/" + folder + "/WalkW1.png"));
+        anmWalkW.addFrame(walkW);
+        anmWalkW.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/WalkW2.png")));
+      } else {
+        noAnims = true;
+        anmStandN.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmStandS.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmStandE.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmStandW.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmWalkN.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmWalkN.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmWalkS.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmWalkS.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmWalkE.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmWalkE.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmWalkW.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmWalkW.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmAttackN.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmAttackS.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmAttackE.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+        anmAttackW.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/" + folder + ".png")));
+      }
+      if (!noAnims) {
+        BufferedImage standN, standS, standE, standW;
+        if (getClass().getResource("../images/" + folder + "/StandN.png") == null) {
+          standN = walkN;
+          standS = walkS;
+          standE = walkE;
+          standW = walkW;
+        } else {
+          standN = ImageIO.read(getClass().getResource("../images/" + folder + "/StandN.png"));
+          standS = ImageIO.read(getClass().getResource("../images/" + folder + "/StandS.png"));
+          standE = ImageIO.read(getClass().getResource("../images/" + folder + "/StandE.png"));
+          standW = ImageIO.read(getClass().getResource("../images/" + folder + "/StandW.png"));
+          anmWalkN = new Animation("north", 0, 0, 40, 60, 150, true);
+          anmWalkS = new Animation("south", 0, 0, 40, 60, 150, true);
+          anmWalkE = new Animation("east", 0, 0, 40, 60, 150, true);
+          anmWalkW = new Animation("west", 0, 0, 40, 60, 150, true);
+          anmWalkN.addFrame(walkN);
+          anmWalkN.addFrame(standN);
+          anmWalkN.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/WalkN2.png")));
+          anmWalkN.addFrame(standN);
+          anmWalkS.addFrame(walkS);
+          anmWalkS.addFrame(standS);
+          anmWalkS.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/WalkS2.png")));
+          anmWalkS.addFrame(standS);
+          anmWalkE.addFrame(walkE);
+          anmWalkE.addFrame(standE);
+          anmWalkE.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/WalkE2.png")));
+          anmWalkE.addFrame(standE);
+          anmWalkW.addFrame(walkW);
+          anmWalkW.addFrame(standW);
+          anmWalkW.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/WalkW2.png")));
+          anmWalkW.addFrame(standW);
+        } 
+        anmStandN.addFrame(standN);
+        anmStandS.addFrame(standS);
+        anmStandE.addFrame(standE);
+        anmStandW.addFrame(standW);
+        if (getClass().getResource("../images/" + folder + "/AttackN.png") != null) {
+          anmAttackN.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackN.png")));
+          anmAttackN.addFrame(standN);
+          anmAttackS.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackS.png")));
+          anmAttackS.addFrame(standS);
+          anmAttackE.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackE.png")));
+          anmAttackE.addFrame(standE);
+          anmAttackW.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackW.png")));
+          anmAttackW.addFrame(standW);
+        } else if (getClass().getResource("../images/" + folder + "/AttackN1.png") != null) {
+          anmAttackN.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackN1.png")));
+          anmAttackN.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackN2.png")));
+          anmAttackS.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackS1.png")));
+          anmAttackS.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackS2.png")));
+          anmAttackE.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackE1.png")));
+          anmAttackE.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackE2.png")));
+          anmAttackW.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackW1.png")));
+          anmAttackW.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/AttackW2.png")));
+        } else {
+          anmAttackN.addFrame(standN);
+          anmAttackS.addFrame(standS);
+          anmAttackE.addFrame(standE);
+          anmAttackW.addFrame(standW);
+        } 
+        if (hasDeathAnim) {
+          anmDeath.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/Death1.png")));
+          anmDeath.addFrame(ImageIO.read(getClass().getResource("../images/" + folder + "/Death2.png")));
+        } 
+      }
+    } catch (IOException ioe) {
+      ioe.printStackTrace();
+    }
+    Model model = new Model(hasDeathAnim);
+    model.addAnimation(Direction.North, Action.Standing, anmStandN);
+    model.addAnimation(Direction.South, Action.Standing, anmStandS);
+    model.addAnimation(Direction.East, Action.Standing, anmStandE);
+    model.addAnimation(Direction.West, Action.Standing, anmStandW);
+    model.addAnimation(Direction.North, Action.Walking, anmWalkN);
+    model.addAnimation(Direction.South, Action.Walking, anmWalkS);
+    model.addAnimation(Direction.East, Action.Walking, anmWalkE);
+    model.addAnimation(Direction.West, Action.Walking, anmWalkW);
+    model.addAnimation(Direction.North, Action.Attacking, anmAttackN);
+    model.addAnimation(Direction.South, Action.Attacking, anmAttackS);
+    model.addAnimation(Direction.East, Action.Attacking, anmAttackE);
+    model.addAnimation(Direction.West, Action.Attacking, anmAttackW);
+    if (hasDeathAnim) {
+      model.addAnimation(Direction.West, Action.Dying, anmDeath);
+    }
+    return model;
+  }
+
+  public void load(BufferedReader in) {
+    try {
+      this.spawnPoint = LostHavenRPG.getSpawnPoint(Integer.parseInt(in.readLine()));
+      if (this.spawnPoint != null) {
+        this.spawnPoint.numSpawns++;
+      } 
+      String strLoc = in.readLine();
+      getLoc().setX(Integer.valueOf(strLoc.substring(0, strLoc.indexOf(","))).intValue());
+      getLoc().setY(Integer.valueOf(strLoc.substring(strLoc.indexOf(",") + 1)).intValue());
+      getModel().setDirection(Direction.valueOf(in.readLine()));
+      getModel().setAction(Action.valueOf(in.readLine()));
+      setHitpoints(Integer.valueOf(in.readLine()).intValue());
+      setManapoints(Integer.valueOf(in.readLine()).intValue());
+      this.passive = Integer.valueOf(in.readLine()).intValue();
+      this.thorns = Integer.valueOf(in.readLine()).intValue();
+      this.confused = Integer.valueOf(in.readLine()).intValue();
+      this.sand = Integer.valueOf(in.readLine()).intValue();
+      String strWeapon = in.readLine();
+      if (!strWeapon.equals("None")) {
+        setWeapon((Weapon)LostHavenRPG.items.get(strWeapon));
+      }
+    } catch (IOException ioe) {
+      ioe.printStackTrace();
+    }
+  }
+
+  protected int attributeIndex(Attribute attribute) {
+    switch (attribute) {
+      case Strength:
+        return 0;
+      case Dexterity:
+        return 1;
+      case Constitution:
+        return 2;
+      case Wisdom:
+        return 3;
+    }
+    return -1;
+  }
+
+  public int getAttribute(Attribute attribute) {
+    return this.attributes[attributeIndex(attribute)];
+  }
+
+  public void setAttribute(Attribute attribute, int num) {
+    this.attributes[attributeIndex(attribute)] = num;
+    updateStats();
+  }
+
+  private void updateStats() {
+    this.hitpoints = 2 * this.attributes[2];
+    this.maxHitpoints = 2 * this.attributes[2];
+    this.manapoints = 2 * this.attributes[3];
+    this.maxManapoints = 2 * this.attributes[3];
+  }
+
+  public Creature getEnemyTarget() {
+    return this.enemyTarget;
+  }
+
+  public int getExperience() {
+    return this.experience;
+  }
+
+  public int getHitpoints() {
+    return this.hitpoints;
+  }
+
+  public Model getModel() {
+    return this.model;
+  }
+
+  public long getLastAttacked() {
+    return this.lastAttacked;
+  }
+
+  public long getLastMoved() {
+    return this.lastMoved;
+  }
+
+  public int getLevel() {
+    return this.level;
+  }
+
+  public Point getLoc() {
+    return this.loc;
+  }
+
+  public int getManapoints() {
+    return this.manapoints;
+  }
+
+  public int getMaxHitpoints() {
+    return this.maxHitpoints;
+  }
+
+  public int getMaxManapoints() {
+    return this.maxManapoints;
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public int getSpeed() {
+    return this.speed;
+  }
+
+  public Point getTarget() {
+    return this.target;
+  }
+
+  public CreatureType getType() {
+    return this.type;
+  }
+
+  public EquippedWeapon getWeapon() {
+    return this.weapon;
+  }
+
+  public EquippedWeapon getSpell() {
+    return this.spell;
+  }
+
+  public void setEnemyTarget(Creature enemyTarget) {
+    this.enemyTarget = enemyTarget;
+  }
+
+  public void setExperience(int experience) {
+    this.experience = experience;
+  }
+
+  public void setHitpoints(int hitpoints) {
+    if (hitpoints > 0) {
+      this.hitpoints = hitpoints;
+    } else {
+      this.hitpoints = 0;
+    }
+  }
+
+  public void setModel(Model model) {
+    this.model = model;
+  }
+
+  public void setLastAttacked(long lastAttacked) {
+    this.lastAttacked = lastAttacked;
+  }
+
+  public void setLastMoved(long lastMoved) {
+    this.lastMoved = lastMoved;
+  }
+
+  public void setLevel(int level) {
+    this.level = level;
+  }
+
+  public void setLoc(Point loc) {
+    this.loc = loc;
+  }
+
+  public void setManapoints(int manapoints) {
+    if (manapoints > 0) {
+      this.manapoints = manapoints;
+    } else {
+      this.manapoints = 0;
+    }
+  }
+
+  public void setMaxHitpoints(int maxHitpoints) {
+    this.maxHitpoints = maxHitpoints;
+  }
+
+  public void setMaxManapoints(int maxManapoints) {
+    this.maxManapoints = maxManapoints;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public void setSpeed(int speed) {
+    this.speed = speed;
+  }
+
+  public void setTarget(Point target) {
+    this.target = target;
+  }
+
+  public void setType(CreatureType type) {
+    this.type = type;
+  }
+
+  public void setWeapon(Weapon weapon) {
+    this.weapon = new EquippedWeapon(this, weapon);
+    this.weapon.update();
+    (this.model.getAnimation(Direction.North, Action.Attacking)).drawInterval = (this.weapon.getAttackSpeed() * 100 / (this.model.getAnimation(Direction.North, Action.Attacking)).frames.size());
+    (this.model.getAnimation(Direction.South, Action.Attacking)).drawInterval = (this.weapon.getAttackSpeed() * 100 / (this.model.getAnimation(Direction.South, Action.Attacking)).frames.size());
+    (this.model.getAnimation(Direction.East, Action.Attacking)).drawInterval = (this.weapon.getAttackSpeed() * 100 / (this.model.getAnimation(Direction.East, Action.Attacking)).frames.size());
+    (this.model.getAnimation(Direction.West, Action.Attacking)).drawInterval = (this.weapon.getAttackSpeed() * 100 / (this.model.getAnimation(Direction.West, Action.Attacking)).frames.size());
+  }
+
+  public void setSpell(Weapon spell) {
+    this.spell = new EquippedWeapon(this, spell);
+    this.spell.update();
+  }
+
+  public SpawnPoint getSpawnPoint() {
+    return this.spawnPoint;
+  }
+
+  public void setSpawnPoint(SpawnPoint sp) {
+    this.spawnPoint = sp;
+  }
+
+  public boolean farFromSpawnPoint() {
+    if (this.spawnPoint == null)
+      return false; 
+    return (Point.dist(this.spawnPoint.getLoc(), this.loc) > 800.0D);
+  }
+
+  public boolean closerToSpawnPoint(Point newLoc) {
+    if (this.spawnPoint == null)
+      return false; 
+    return (Point.dist(this.spawnPoint.getLoc(), this.loc) >= Point.dist(this.spawnPoint.getLoc(), newLoc));
+  }
+
+  public void disable() {
+    this.disabled = true;
+  }
+
+  public void enable() {
+    this.disabled = false;
+  }
+
+  public String toString() {
+    return this.name;
+  }
+
+  public int compareTo(Creature c) {
+    return 0;
+  }
 }
