Index: main/Player.java
===================================================================
--- main/Player.java	(revision 08704682fb409c42246c2544c64a8681a3fd9734)
+++ main/Player.java	(revision b2d7893da9fa84a56da5703be7a5610992874d30)
@@ -1,46 +1,453 @@
 package main;
 
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.MouseInfo;
+import java.io.*;
+import java.util.*;
+
+import gamegui.*;
+
 public class Player extends Creature {
-	private Point target;
-	private int experience;
-	private int gold;
-	
-	public Player() {
-		super();
-		target = new Point(0, 0);
-	}
-
-	public Player(String name) {
-		super(name);
-		target = new Point(0, 0);
-	}
-	
-	public Player(String name, Gender gender) {
-		super(name, gender);
-		target = new Point(0, 0);
-	}
-	
-	public int getExperience() {
-		return experience;
-	}
-	
-	public int getGold() {
-		return gold;
-	}
-	
-	public Point getTarget() {
-		return target;
-	}
-	
-	public void setExperience(int experience) {
-		this.experience = experience;
-	}
-	
-	public void setGold(int gold) {
-		this.gold = gold;
-	}
-	
-	public void setTarget(Point target) {
-		this.target = target;
-	}
+
+  private int gold;
+  private int attributePoints;
+  private int[] skills;
+  private int skillPoints;
+  private LinkedList<Item> inventory;
+  private LinkedList<Item> gemsUsed;
+  private HashMap<Gem, Integer> gems;
+  private int relicCount;
+  private int gemValue;
+  private long timePlayed;
+  private long timeLoggedOn;
+
+  public Player() {
+    this.name = "Player";
+    this.type = CreatureType.Player;
+    this.skills = new int[9];
+    this.inventory = new LinkedList<Item>();
+    this.gemsUsed = new LinkedList<Item>();
+    this.gems = new HashMap<Gem, Integer>();
+    this.relicCount = 0;
+    this.gemValue = 0;
+    this.timePlayed = 0L;
+    this.timeLoggedOn = 0L;
+  }
+
+  public Player(Player p) {
+    super(p);
+    this.skills = (int[])p.skills.clone();
+    this.attributePoints = p.attributePoints;
+    this.skillPoints = p.skillPoints;
+    this.inventory = new LinkedList<Item>(p.inventory);
+    this.gemsUsed = new LinkedList<Item>(p.gemsUsed);
+    this.gems = new HashMap<Gem, Integer>(p.gems);
+    this.relicCount = p.relicCount;
+    this.gemValue = p.gemValue;
+    this.timePlayed = p.timePlayed;
+    this.timeLoggedOn = p.timeLoggedOn;
+  }
+
+  public Player copy() {
+    return new Player(this);
+  }
+
+  public boolean readyForBoss() {
+    return (this.relicCount >= 4);
+  }
+
+  public void setTimeLoggedOn(long time) {
+    this.timeLoggedOn = time;
+  }
+
+  public long getTimePlayed() {
+    return this.timePlayed;
+  }
+
+  public void updateTimePlayed() {
+    this.timePlayed += System.currentTimeMillis() - this.timeLoggedOn;
+  }
+
+  public void drawInventory(Graphics g, ScrollList inv, int x, int y) {
+    int mouseX = (MouseInfo.getPointerInfo().getLocation()).x;
+    int mouseY = (MouseInfo.getPointerInfo().getLocation()).y;
+    int locX = (mouseX - x) / 50;
+    int locY = (mouseY - y + inv.getTextStart()) / 50;
+    if (locX + 4 * locY >= 0 && locX + 4 * locY < inv.getList().size()) {
+      Window popup;
+      String itemType;
+      MultiTextbox desc;
+      Item i = ((ItemImg)inv.getList().get(locX + locY * 4)).getItem();
+      switch (i.getType()) {
+        case Relic:
+          popup = new Window("popup", mouseX - 100, mouseY - 150, 100, 165, false);
+          break;
+        default:
+          popup = new Window("popup", mouseX - 100, mouseY - 100, 100, 100, false);
+          break;
+      }
+      Font font12 = new Font("Arial", 0, 12);
+      switch (i.getType()) {
+        case LightWeapon:
+          itemType = "Light Weapon";
+          break;
+        case HeavyWeapon:
+          itemType = "Heavy Weapon";
+          break;
+        case RangedWeapon:
+          itemType = "Ranged Weapon";
+          break;
+        default:
+          itemType = i.getType().toString();
+          break;
+      }
+      popup.add(new Label("name", 5, 5, 90, 15, i.getName(), font12));
+      popup.add(new Label("type", 5, 35, 90, 15, itemType, font12));
+      switch (i.getType()) {
+        case LightWeapon:
+        case HeavyWeapon:
+        case RangedWeapon:
+          popup.add(new Label("damage", 5, 50, 90, 15, "Damage: " + ((Weapon)i).getDamage(), font12));
+          popup.add(new Label("damage", 5, 65, 90, 15, "Cooldown: " + (((Weapon)i).getAttackSpeed() / 10.0D) + " s", font12));
+          break;
+        case Spell:
+          popup.add(new Label("energy", 5, 50, 90, 15, "Energy: " + ((Gem)i).getValue(), font12));
+          desc = new MultiTextbox("description", 1, 80, 99, 84, "", false, font12, g.getFontMetrics(font12));
+          desc.setText(i.getDescription());
+          desc.setBorder(false);
+          popup.add(desc);
+          break;
+      }
+      popup.draw(g);
+    }
+  }
+
+  public void save(PrintWriter out) {
+    super.save(out);
+    out.println(this.name);
+    out.println(this.level);
+    out.println(this.timePlayed);
+    out.println(this.experience);
+    out.println(String.valueOf(getTarget().getX()) + "," + getTarget().getY());
+    out.println(getAttribute(Attribute.Strength));
+    out.println(getAttribute(Attribute.Dexterity));
+    out.println(getAttribute(Attribute.Constitution));
+    out.println(getAttribute(Attribute.Wisdom));
+    out.println(getSkill(Skill.LightWeapons));
+    out.println(getSkill(Skill.HeavyWeapons));
+    out.println(getSkill(Skill.RangedWeapons));
+    out.println(getSkill(Skill.Evocation));
+    out.println(getSkill(Skill.Enchantment));
+    out.println(this.attributePoints);
+    out.println(this.skillPoints);
+    out.println(getMaxHitpoints());
+    out.println(getMaxManapoints());
+    Object[] arr = LostHavenRPG.respawnPoints.toArray();
+    for (int x = 0; x < arr.length; x++) {
+      if (((RespawnPoint)arr[x]).isMarked())
+        out.println(x); 
+    }
+    out.println("---");
+    Iterator<Item> iter = this.inventory.iterator();
+    while (iter.hasNext())
+      out.println(((Item)iter.next()).getName()); 
+    out.println("---");
+    iter = this.gemsUsed.iterator();
+    while (iter.hasNext())
+      out.println(((Item)iter.next()).getName()); 
+    out.println("---");
+  }
+
+  public static Player loadTemplate(BufferedReader in) {
+    Player p = new Player();
+    try {
+      p.level = Integer.parseInt(in.readLine());
+      p.setSkill(Skill.LightWeapons, Integer.parseInt(in.readLine()));
+      p.setSkill(Skill.HeavyWeapons, Integer.parseInt(in.readLine()));
+      p.setSkill(Skill.RangedWeapons, Integer.parseInt(in.readLine()));
+      p.setSkill(Skill.Evocation, Integer.parseInt(in.readLine()));
+      p.setSkill(Skill.Enchantment, Integer.parseInt(in.readLine()));
+      p.attributePoints = Integer.parseInt(in.readLine());
+      p.skillPoints = Integer.parseInt(in.readLine());
+    } catch (IOException ioe) {
+      ioe.printStackTrace();
+    }
+    return p;
+  }
+
+  public void load(BufferedReader in) {
+    try {
+      super.load(in);
+      int hp = getHitpoints();
+      int mp = getManapoints();
+      setName(in.readLine());
+      this.level = Integer.valueOf(in.readLine()).intValue();
+      this.timePlayed = Long.valueOf(in.readLine()).longValue();
+      setExperience(Integer.valueOf(in.readLine()).intValue());
+      String strTarget = in.readLine();
+      getTarget().setX(Integer.valueOf(strTarget.substring(0, strTarget.indexOf(","))).intValue());
+      getTarget().setY(Integer.valueOf(strTarget.substring(strTarget.indexOf(",") + 1)).intValue());
+      setAttribute(Attribute.Strength, Integer.parseInt(in.readLine()));
+      setAttribute(Attribute.Dexterity, Integer.parseInt(in.readLine()));
+      setAttribute(Attribute.Constitution, Integer.parseInt(in.readLine()));
+      setAttribute(Attribute.Wisdom, Integer.parseInt(in.readLine()));
+      setSkill(Skill.LightWeapons, Integer.parseInt(in.readLine()));
+      setSkill(Skill.HeavyWeapons, Integer.parseInt(in.readLine()));
+      setSkill(Skill.RangedWeapons, Integer.parseInt(in.readLine()));
+      setSkill(Skill.Evocation, Integer.parseInt(in.readLine()));
+      setSkill(Skill.Enchantment, Integer.parseInt(in.readLine()));
+      this.attributePoints = Integer.parseInt(in.readLine());
+      this.skillPoints = Integer.parseInt(in.readLine());
+      setMaxHitpoints(Integer.parseInt(in.readLine()));
+      setMaxManapoints(Integer.parseInt(in.readLine()));
+      setHitpoints(hp);
+      setManapoints(mp);
+      setWeapon(this.weapon.baseWeapon);
+      String strItem;
+      while (!(strItem = in.readLine()).equals("---"))
+        ((RespawnPoint)LostHavenRPG.respawnPoints.get(Integer.parseInt(strItem))).mark(); 
+      this.weapon.update();
+      while (!(strItem = in.readLine()).equals("---"))
+        pickUp(LostHavenRPG.items.get(strItem)); 
+      while (!(strItem = in.readLine()).equals("---")) {
+        pickUp(LostHavenRPG.items.get(strItem));
+        activateGem((Gem)LostHavenRPG.items.get(strItem));
+      }
+    } catch (IOException ioe) {
+      ioe.printStackTrace();
+    }
+  }
+
+  public void pickUp(Item item) {
+    this.inventory.add(item);
+    LostHavenRPG.lstInventory.getList().add(new ItemImg(item));
+    if (item.isRelic()) {
+      this.relicCount++;
+    }
+  }
+
+  public boolean activateGem(Gem item) {
+    if (this.gemValue + item.getValue() > getSkill(Skill.Evocation))
+      return false; 
+    this.gemsUsed.add(item);
+    LostHavenRPG.lstGems.getList().add(new ItemImg(item));
+    this.inventory.remove(item);
+    LostHavenRPG.lstInventory.getList().remove(new ItemImg(item));
+    this.gemValue += item.getValue();
+    addGem((Gem)LostHavenRPG.items.get(item.getName()));
+    if (getSpell() == null) {
+      setSpell(new Weapon("spell", ItemType.Spell, "Dagger.png", new java.awt.image.BufferedImage[8], 10, 250, 0)); 
+    }
+    getSpell().update();
+    return true;
+  }
+
+  public void deactivateGem(Gem item) {
+    this.inventory.add(item);
+    LostHavenRPG.lstInventory.getList().add(new ItemImg(item));
+    this.gemsUsed.remove(item);
+    LostHavenRPG.lstGems.getList().remove(new ItemImg(item));
+    this.gemValue -= item.getValue();
+    removeGem((Gem)LostHavenRPG.items.get(item.getName()));
+    if (this.gemsUsed.size() == 0) {
+      this.spell = null;
+    } else {
+      getSpell().update();
+    }
+  }
+
+  public LinkedList<Item> getInventory() {
+    return this.inventory;
+  }
+
+  public LinkedList<Item> getGems() {
+    return this.gemsUsed;
+  }
+
+  public void initGems(LinkedList<Gem> lstGems) {
+    Iterator<Gem> iter = lstGems.iterator();
+    while (iter.hasNext())
+      this.gems.put(iter.next(), Integer.valueOf(0)); 
+  }
+
+  public void addGem(Gem gem) {
+    this.gems.put(gem, Integer.valueOf(((Integer)this.gems.get(gem)).intValue() + 1));
+  }
+
+  public void removeGem(Gem gem) {
+    this.gems.put(gem, Integer.valueOf(((Integer)this.gems.get(gem)).intValue() - 1));
+  }
+
+  public int getGemNum(String name) {
+    Iterator<Gem> iter = this.gems.keySet().iterator();
+    while (iter.hasNext()) {
+      Gem cur = iter.next();
+      if (cur.getName().equals(name)) {
+        return ((Integer)this.gems.get(cur)).intValue();
+      }
+    }
+    return 0;
+  }
+
+  public void increaseLevel() {
+    this.skillPoints += 2;
+    setHitpoints(getHitpoints() + getAttribute(Attribute.Constitution));
+    setMaxHitpoints(getMaxHitpoints() + getAttribute(Attribute.Constitution));
+    setManapoints(getManapoints() + getAttribute(Attribute.Wisdom));
+    setMaxManapoints(getMaxManapoints() + getAttribute(Attribute.Wisdom));
+    setLevel(getLevel() + 1);
+  }
+
+  public void allocateAttribute(Attribute point) {
+    if (this.attributePoints > 0) {
+      setAttribute(point, getAttribute(point) + 1);
+      this.attributePoints--;
+    }
+  }
+
+  public void repickAttribute(Attribute point) {
+    if (getAttribute(point) > 6) {
+      setAttribute(point, getAttribute(point) - 1);
+      this.attributePoints++;
+    }
+  }
+
+  public void allocateSkill(Skill point) {
+    if (this.skillPoints > 0) {
+      setSkill(point, getSkill(point) + 1);
+      this.skillPoints--;
+      this.weapon.update();
+    }
+  }
+
+  public void repickSkill(Skill point) {
+    if (getSkill(point) > 0) {
+      setSkill(point, getSkill(point) - 1);
+      this.skillPoints++;
+      this.weapon.update();
+    }
+  }
+
+  private int skillIndex(Skill skill) {
+    switch (skill) {
+      case LightWeapons:
+        return 0;
+      case HeavyWeapons:
+        return 1;
+      case RangedWeapons:
+        return 2;
+      case Evocation:
+        return 3;
+      case Enchantment:
+        return 4;
+    }
+    return -1;
+  }
+
+  public int getSkill(Skill skill) {
+    return this.skills[skillIndex(skill)];
+  }
+
+  public void setSkill(Skill skill, int num) {
+    this.skills[skillIndex(skill)] = num;
+  }
+
+  public int getGold() {
+    return this.gold;
+  }
+
+  public int getAttributePoints() {
+    return this.attributePoints;
+  }
+
+  public int getSkillPoints() {
+    return this.skillPoints;
+  }
+
+  public int getGemValue() {
+    return this.gemValue;
+  }
+
+  public int getRelicCount() {
+    return this.relicCount;
+  }
+
+  public void setWeapon(Weapon weapon) {
+    this.weapon = new EquippedWeapon(this, weapon);
+    switch (weapon.getType()) {
+      case LightWeapon:
+      case HeavyWeapon:
+        setModel(LostHavenRPG.meleeModel);
+        break;
+      case RangedWeapon:
+        setModel(LostHavenRPG.rangedModel);
+        break;
+    }
+    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 setGold(int gold) {
+    this.gold = gold;
+  }
+
+  public void setAttributePoints(int attributePoints) {
+    this.attributePoints = attributePoints;
+  }
+
+  public void setAttribute(Attribute attribute, int num) {
+    this.attributes[attributeIndex(attribute)] = num;
+    updateStats();
+  }
+
+  private void updateStats() {
+    this.hitpoints = 4 * this.attributes[2];
+    this.maxHitpoints = 4 * this.attributes[2];
+    this.manapoints = 2 * this.attributes[3];
+    this.maxManapoints = 2 * this.attributes[3];
+  }
+
+  public class ItemImg implements Listable {
+    public Item i;
+    public int xCoord;
+    public int yCoord;
+
+    public ItemImg(Item i) {
+      this.i = i;
+    }
+
+    public void draw(int x, int y, Graphics g) {
+      this.xCoord = x;
+      this.yCoord = y;
+      this.i.drawStatic(g, x, y);
+    }
+
+    public Item getItem() {
+      return this.i;
+    }
+
+    public int getHeight() {
+      return this.i.getImg().getHeight();
+    }
+
+    public int getWidth() {
+      return this.i.getImg().getWidth();
+    }
+
+    public int getXOffset() {
+      return 0;
+    }
+
+    public int getYOffset() {
+      return 0;
+    }
+
+    public boolean equals(Object o) {
+      return (((ItemImg)o).i == this.i);
+    }
+  }
 }
