diff --git a/src/main/java/com/comandante/creeper/command/LookCommand.java b/src/main/java/com/comandante/creeper/command/LookCommand.java
index 1a0062af9db8813e0b547cb4cce9b6b0448e7177..6c09973648ca77236ca7705c3b1d709698d52ac8 100644
--- a/src/main/java/com/comandante/creeper/command/LookCommand.java
+++ b/src/main/java/com/comandante/creeper/command/LookCommand.java
@@ -3,6 +3,7 @@ package com.comandante.creeper.command;
 
 import com.comandante.creeper.managers.GameManager;
 import com.comandante.creeper.npc.Npc;
+import com.comandante.creeper.player.Levels;
 import com.comandante.creeper.player.Player;
 import com.google.common.base.Joiner;
 import org.jboss.netty.channel.ChannelHandlerContext;
@@ -53,7 +54,7 @@ public class LookCommand extends Command {
             for (String npcId : npcIds) {
                 Npc currentNpc = gameManager.getEntityManager().getNpcEntity(npcId);
                 if (currentNpc.getValidTriggers().contains(target)) {
-                    write(gameManager.getLookString(currentNpc) + "\r\n");
+                    write(gameManager.getLookString(currentNpc, Levels.getLevel(gameManager.getStatsModifierFactory().getStatsModifier(player).getExperience())) + "\r\n");
                 }
             }
         } finally {
diff --git a/src/main/java/com/comandante/creeper/managers/GameManager.java b/src/main/java/com/comandante/creeper/managers/GameManager.java
index 215f741d70c0e6410a7e49ef65a1f532551798ae..ce01d8f30c48ae78f1533c73a1d5cd8e0d7d5ca2 100755
--- a/src/main/java/com/comandante/creeper/managers/GameManager.java
+++ b/src/main/java/com/comandante/creeper/managers/GameManager.java
@@ -410,10 +410,11 @@ public class GameManager {
         }
     }
 
-    public String getLookString(Npc npc) {
+    public String getLookString(Npc npc, long playerLevel) {
         StringBuilder sb = new StringBuilder();
         // passing an empty createState because of the "difference calculation"
         sb.append(Color.MAGENTA + "-+=[ " + Color.RESET).append(npc.getColorName()).append(Color.MAGENTA + " ]=+- " + Color.RESET).append("\r\n");
+        sb.append("Level ").append(Levels.getLevel(npc.getStats().getExperience())).append(" ").append(npc.getLevelColor((int) playerLevel).getColor()).append("\r\n");
         sb.append(Color.MAGENTA + "Stats--------------------------------" + Color.RESET).append("\r\n");
         sb.append(buildLookString(npc.getColorName(), npc.getStats(), new StatsBuilder().createStats())).append("\r\n");
         if (npc.getEffects() != null && npc.getEffects().size() > 0) {
@@ -616,13 +617,13 @@ public class GameManager {
             long amount = damageEntry.getValue();
             double pct = (double) amount / totalDamageDone;
             if (pct >= .90) {
-                damagePcts.put(playerId, npc.getPctOFExperience(1, Levels.getLevel(playerMetadata.getStats().getExperience())));
+                damagePcts.put(playerId, (double) 1);
             } else if (pct >= 0.25) {
-                damagePcts.put(playerId, npc.getPctOFExperience(.8, Levels.getLevel(playerMetadata.getStats().getExperience())));
+                damagePcts.put(playerId, .8);
             } else if (pct >= 0.10) {
-                damagePcts.put(playerId, npc.getPctOFExperience(.5, Levels.getLevel(playerMetadata.getStats().getExperience())));
+                damagePcts.put(playerId, .5);
             } else {
-                damagePcts.put(playerId, npc.getPctOFExperience(.25, Levels.getLevel(playerMetadata.getStats().getExperience())));
+                damagePcts.put(playerId, .25);
             }
         }
         return damagePcts;
diff --git a/src/main/java/com/comandante/creeper/npc/Npc.java b/src/main/java/com/comandante/creeper/npc/Npc.java
index 98ff0ac2bfc36fc656b5ed1cc6778b4a5c394ce1..1e8a1821122e6ab32cb78db78eb009fa63cdce29 100644
--- a/src/main/java/com/comandante/creeper/npc/Npc.java
+++ b/src/main/java/com/comandante/creeper/npc/Npc.java
@@ -9,6 +9,7 @@ import com.comandante.creeper.managers.GameManager;
 import com.comandante.creeper.managers.SentryManager;
 import com.comandante.creeper.player.CoolDown;
 import com.comandante.creeper.player.CoolDownType;
+import com.comandante.creeper.player.Levels;
 import com.comandante.creeper.player.Player;
 import com.comandante.creeper.server.Color;
 import com.comandante.creeper.spawner.SpawnRule;
@@ -79,6 +80,8 @@ public class Npc extends CreeperEntity {
             try {
                 if (isAlive.get()) {
                     if (effectsTickBucket == 5) {
+
+                        // START Process NPC Effects
                         for (Effect effect : effects) {
                             if (effect.getEffectApplications() >= effect.getMaxEffectApplications()) {
                                 Optional<Room> npcCurrentRoom = gameManager.getRoomManager().getNpcCurrentRoom(this);
@@ -96,10 +99,13 @@ public class Npc extends CreeperEntity {
                                 gameManager.getEntityManager().saveEffect(effect);
                             }
                         }
+                        // END Process Npc Effects
+
                         effectsTickBucket = 0;
                     } else {
                         effectsTickBucket++;
                     }
+
                     List<NpcStatsChange> npcStatsChangeList = Lists.newArrayList();
                     npcStatsChanges.drainTo(npcStatsChangeList);
                     for (NpcStatsChange npcStatsChange : npcStatsChangeList) {
@@ -200,7 +206,7 @@ public class Npc extends CreeperEntity {
 
     public Optional<SpawnRule> getSpawnRuleByArea(Area area) {
         Set<SpawnRule> spawnRules = getSpawnRules();
-        for (SpawnRule spawnRule: spawnRules) {
+        for (SpawnRule spawnRule : spawnRules) {
             if (spawnRule.getArea().equals(area)) {
                 return Optional.of(spawnRule);
             }
@@ -254,7 +260,7 @@ public class Npc extends CreeperEntity {
         if (!isActiveCooldown(CoolDownType.NPC_FIGHT)) {
             addCoolDown(new CoolDown(CoolDownType.NPC_FIGHT));
         } else {
-            for (CoolDown coolDown: coolDowns) {
+            for (CoolDown coolDown : coolDowns) {
                 if (coolDown.getCoolDownType().equals(CoolDownType.NPC_FIGHT)) {
                     coolDown.setNumberOfTicks(coolDown.getOriginalNumberOfTicks());
                 }
@@ -321,7 +327,6 @@ public class Npc extends CreeperEntity {
             }
         } catch (Exception e) {
             SentryManager.logSentry(this.getClass(), e, "Problem processing NPC Stat Change!");
-
         }
     }
 
@@ -362,12 +367,12 @@ public class Npc extends CreeperEntity {
 
     private void killNpc(Player player) {
         isAlive.set(false);
-        Map<String, Double> xpProcessed;
+        Map<String, Double> damagePercents;
         Item corpse = new Item(getName() + " corpse", "a bloody corpse.", Arrays.asList("corpse", "c"), "a corpse lies on the ground.", UUID.randomUUID().toString(), Item.CORPSE_ID_RESERVED, 0, false, 120, Rarity.BASIC, 0, getLoot());
         if (!player.isActive(CoolDownType.DEATH)) {
             gameManager.writeToPlayerCurrentRoom(player.getPlayerId(), getDieMessage());
         }
-        xpProcessed = gameManager.processExperience(this, getCurrentRoom());
+        damagePercents = gameManager.processExperience(this, getCurrentRoom());
         gameManager.getEntityManager().saveItem(corpse);
         Integer roomId = gameManager.getRoomManager().getNpcCurrentRoom(this).get().getRoomId();
         Room room = gameManager.getRoomManager().getRoom(roomId);
@@ -376,15 +381,140 @@ public class Npc extends CreeperEntity {
         getCurrentRoom().removePresentNpc(getEntityId());
         gameManager.getEntityManager().deleteNpcEntity(getEntityId());
         player.removeActiveFight(this);
-        for (Map.Entry<String, Double> playerDamageExperience : xpProcessed.entrySet()) {
-            Player p = gameManager.getPlayerManager().getPlayer(playerDamageExperience.getKey());
+        for (Map.Entry<String, Double> playerDamagePercent : damagePercents.entrySet()) {
+            Player p = gameManager.getPlayerManager().getPlayer(playerDamagePercent.getKey());
             if (p == null) {
                 continue;
             }
-            long xpEarned = (long) Math.round(playerDamageExperience.getValue());
+            Double playerDamagePercentValue = playerDamagePercent.getValue();
+
+            int playerLevel = (int) Levels.getLevel(gameManager.getStatsModifierFactory().getStatsModifier(player).getExperience());
+            int npcLevel = (int) Levels.getLevel(this.getStats().getExperience());
+
+            long xpEarned = (long) (getNpcXp(playerLevel, npcLevel) * playerDamagePercentValue);
             p.addExperience(xpEarned);
             gameManager.getChannelUtils().write(p.getPlayerId(), getBattleReport(xpEarned) + "\r\n", true);
         }
     }
 
+    public static enum NpcLevelColor {
+
+        RED(Color.RED + "Red"),
+        ORANGE(Color.CYAN + "Cyan"),
+        YELLOW(Color.YELLOW + "Yellow"),
+        GREEN(Color.GREEN + "Green"),
+        WHITE(Color.WHITE + "White");
+
+        private final String color;
+
+        NpcLevelColor(String color) {
+            this.color = color;
+        }
+
+        public String getColor() {
+            return "(" + Color.BOLD_ON + color + Color.RESET + ")";
+        }
+    }
+
+    public NpcLevelColor getLevelColor(int playerLevel) {
+        int npcLevel = (int) Levels.getLevel(this.getStats().getExperience());
+
+        if (playerLevel + 5 <= npcLevel) {
+            return NpcLevelColor.RED;
+        } else {
+            switch (npcLevel - playerLevel) {
+                case 4:
+                case 3:
+                    return NpcLevelColor.ORANGE;
+                case 2:
+                case 1:
+                case 0:
+                case -1:
+                case -3:
+                    return NpcLevelColor.YELLOW;
+                default:
+                    if (playerLevel <= 5) {
+                        return NpcLevelColor.GREEN;
+                    } else {
+                        if (playerLevel <= 50) {
+                            if (npcLevel <= (playerLevel - 5 - Math.floor(playerLevel / 10))) {
+                                return NpcLevelColor.WHITE;
+                            } else {
+                                return NpcLevelColor.GREEN;
+                            }
+                        } else {
+                            // Player is over level 50
+                            if (npcLevel <= (playerLevel - 1 - Math.floor(playerLevel / 5))) {
+                                return NpcLevelColor.WHITE;
+                            } else {
+                                return NpcLevelColor.GREEN;
+                            }
+                        }
+                    }
+            }
+        }
+    }
+
+    private int getNpcXp(int playerLevel, int npcLevel) {
+        if (npcLevel >= playerLevel) {
+            double temp = ((playerLevel * 5) + 45) * (1 + (0.05 * (npcLevel - playerLevel)));
+            double tempCap = ((playerLevel * 5) + 45) * 1.2;
+            if (temp > tempCap) {
+                return (int) Math.floor(tempCap);
+            } else {
+                return (int) Math.floor(temp);
+            }
+        } else {
+            if (getLevelColor(playerLevel).equals(NpcLevelColor.WHITE)) {
+                return 0;
+            } else {
+                return (int) (Math.floor((playerLevel * 5) + 45) * (1 - (playerLevel - npcLevel) / getZD(playerLevel)));
+            }
+        }
+    }
+
+    private int getZD(int lvl) {
+        if (lvl <= 7) {
+            return 5;
+        }
+        if (lvl <= 9) {
+            return 6;
+        }
+        if (lvl <= 11) {
+            return 7;
+        }
+        if (lvl <= 15) {
+            return 8;
+        }
+        if (lvl <= 19) {
+            return 9;
+        }
+        if (lvl <= 29) {
+            return 11;
+        }
+        if (lvl <= 39) {
+            return 12;
+        }
+        if (lvl <= 49) {
+            return 13;
+        }
+        if (lvl <= 59) {
+            return 14;
+        }
+        if (lvl <= 69) {
+            return 15;
+        }
+        if (lvl <= 79) {
+            return 16;
+        }
+        if (lvl <= 89) {
+            return 17;
+        }
+        if (lvl <= 99) {
+            return 18;
+        } else {
+            return 19;
+        }
+    }
+
 }
diff --git a/src/main/java/com/comandante/creeper/player/Levels.java b/src/main/java/com/comandante/creeper/player/Levels.java
index 123a27ebc3be3692f481d82eb4a3dbd531d90695..6eb9ca510aa63b96063b78b3283f7cbbc011e5c4 100644
--- a/src/main/java/com/comandante/creeper/player/Levels.java
+++ b/src/main/java/com/comandante/creeper/player/Levels.java
@@ -5,7 +5,7 @@ import static java.lang.StrictMath.sqrt;
 
 public class Levels {
 
-    private static double CONSTANT_MODIFIER = 0.005;
+    private static double CONSTANT_MODIFIER = 0.02;
 
     public static long getLevel(long experience) {
         double v = CONSTANT_MODIFIER * sqrt(experience);
diff --git a/src/main/java/com/comandante/creeper/player/Player.java b/src/main/java/com/comandante/creeper/player/Player.java
index 4ed831d1e9de4311b904a64eeecd51f953a2f955..a3ded4048fddac62355cbdb929982a320504198b 100755
--- a/src/main/java/com/comandante/creeper/player/Player.java
+++ b/src/main/java/com/comandante/creeper/player/Player.java
@@ -2,6 +2,7 @@ package com.comandante.creeper.player;
 
 
 import com.codahale.metrics.Meter;
+import com.comandante.creeper.Items.ForageManager;
 import com.comandante.creeper.Items.Item;
 import com.comandante.creeper.Items.ItemType;
 import com.comandante.creeper.Main;
@@ -740,7 +741,7 @@ public class Player extends CreeperEntity {
         Stats diffStats = StatsHelper.getDifference(modifiedStats, origStats);
         sb.append(Color.MAGENTA + "-+=[ " + Color.RESET).append(playerName).append(Color.MAGENTA + " ]=+- " + Color.RESET).append("\r\n");
         sb.append("Level ").append(Levels.getLevel(origStats.getExperience())).append("\r\n");
-        sb.append("Foraging Level ").append(gameManager.getForageManager().getLevel(modifiedStats.getForaging())).append("\r\n");
+        sb.append("Foraging Level ").append(ForageManager.getLevel(modifiedStats.getForaging())).append("\r\n");
         sb.append(Color.MAGENTA + "Equip--------------------------------" + Color.RESET).append("\r\n");
         sb.append(buildEquipmentString()).append("\r\n");
         sb.append(Color.MAGENTA + "Stats--------------------------------" + Color.RESET).append("\r\n");
diff --git a/src/test/com/comandante/creeper/player/LevelsTest.java b/src/test/com/comandante/creeper/player/LevelsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..dad461bc3c6d49157aace404fc3ae552c8967676
--- /dev/null
+++ b/src/test/com/comandante/creeper/player/LevelsTest.java
@@ -0,0 +1,30 @@
+package com.comandante.creeper.player;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class LevelsTest {
+
+    @Test
+    public void testLevels() throws Exception {
+        for (int i = 0; i < 100; i++) {
+            long xp = Levels.getXp(i);
+            long level = Levels.getLevel(xp);
+            Assert.assertEquals(level, i);
+            System.out.println("Level: " + i + " | XP: " + xp);
+        }
+    }
+
+    @Test
+    public void printHowMuchXpIsNecessaryToLevelUp() throws Exception {
+        for (int i = 0; i < 100; i++) {
+            long xp = Levels.getXp(i);
+            long level = Levels.getLevel(xp);
+            long xpNext = Levels.getXp(i + 1);
+            long l = xpNext - xp;
+            System.out.println("Level " + i + " to " + (i + 1) + " takes " + l + " xp.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/world/npcs/treeberserker.json b/world/npcs/treeberserker.json
index fb4ff4f6494fc2722c337a23ec7313360289f498..099e28c6b13ee757057892989a33cdbee93544ea 100755
--- a/world/npcs/treeberserker.json
+++ b/world/npcs/treeberserker.json
@@ -16,7 +16,7 @@
     "armorRating": 8,
     "currentHealth": 200,
     "currentMana": 100,
-    "experience": 150,
+    "experience": 22600,
     "maxHealth": 150,
     "maxMana": 100,
     "meleSkill": 6,