Browse Source

Adding AdvancedConfig

TfT_02 12 years ago
parent
commit
0d2abb95b5
37 changed files with 933 additions and 465 deletions
  1. 1 1
      .gitignore
  2. 17 0
      Changelog.txt
  3. 84 82
      src/main/java/com/gmail/nossr50/commands/skills/AcrobaticsCommand.java
  4. 91 72
      src/main/java/com/gmail/nossr50/commands/skills/ArcheryCommand.java
  5. 24 15
      src/main/java/com/gmail/nossr50/commands/skills/AxesCommand.java
  6. 5 1
      src/main/java/com/gmail/nossr50/commands/skills/ExcavationCommand.java
  7. 8 3
      src/main/java/com/gmail/nossr50/commands/skills/FishingCommand.java
  8. 30 44
      src/main/java/com/gmail/nossr50/commands/skills/HerbalismCommand.java
  9. 36 25
      src/main/java/com/gmail/nossr50/commands/skills/MiningCommand.java
  10. 15 8
      src/main/java/com/gmail/nossr50/commands/skills/RepairCommand.java
  11. 26 16
      src/main/java/com/gmail/nossr50/commands/skills/SwordsCommand.java
  12. 28 17
      src/main/java/com/gmail/nossr50/commands/skills/TamingCommand.java
  13. 23 16
      src/main/java/com/gmail/nossr50/commands/skills/UnarmedCommand.java
  14. 15 9
      src/main/java/com/gmail/nossr50/commands/skills/WoodcuttingCommand.java
  15. 152 0
      src/main/java/com/gmail/nossr50/config/AdvancedConfig.java
  16. 16 11
      src/main/java/com/gmail/nossr50/listeners/EntityListener.java
  17. 5 1
      src/main/java/com/gmail/nossr50/listeners/PlayerListener.java
  18. 2 0
      src/main/java/com/gmail/nossr50/mcMMO.java
  19. 8 5
      src/main/java/com/gmail/nossr50/skills/acrobatics/Acrobatics.java
  20. 9 7
      src/main/java/com/gmail/nossr50/skills/archery/Archery.java
  21. 19 11
      src/main/java/com/gmail/nossr50/skills/archery/ArcheryManager.java
  22. 21 12
      src/main/java/com/gmail/nossr50/skills/combat/Axes.java
  23. 26 16
      src/main/java/com/gmail/nossr50/skills/gathering/BlastMining.java
  24. 3 1
      src/main/java/com/gmail/nossr50/skills/gathering/Fishing.java
  25. 8 3
      src/main/java/com/gmail/nossr50/skills/gathering/Mining.java
  26. 8 3
      src/main/java/com/gmail/nossr50/skills/gathering/WoodCutting.java
  27. 22 11
      src/main/java/com/gmail/nossr50/skills/repair/Repair.java
  28. 11 7
      src/main/java/com/gmail/nossr50/skills/swords/Swords.java
  29. 11 5
      src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java
  30. 16 12
      src/main/java/com/gmail/nossr50/skills/taming/Taming.java
  31. 7 3
      src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java
  32. 13 6
      src/main/java/com/gmail/nossr50/skills/unarmed/Unarmed.java
  33. 19 9
      src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java
  34. 6 4
      src/main/java/com/gmail/nossr50/spout/SpoutStuff.java
  35. 4 1
      src/main/java/com/gmail/nossr50/util/Skills.java
  36. 116 0
      src/main/resources/advanced.yml
  37. 28 28
      src/main/resources/locale/locale_en_US.properties

+ 1 - 1
.gitignore

@@ -1,4 +1,4 @@
-# Eclipse stuff
+# Eclipse stuffs
 /.classpath
 /.project
 /.settings

+ 17 - 0
Changelog.txt

@@ -7,6 +7,23 @@ Key:
   ! Change
   - Removal
 
+Version 1.3.12
+ + Added Craftbukkit 1.4.5 compatibility
+ + Added new items from Minecraft 1.4 to Herbalism (potatoes & carrots)
+ + Added new mobs from Minecraft 1.4 checks for every ability
+ + Added new active ability for Repair: Salvage
+ + Added options to 'config.yml' configure shake chance
+ + Added the option to negate experience earned for Herbalism while in a minecart to prevent afk leveling
+ + Added Green thumb now converts cobble walls to mossy cobble walls
+ + Added beacons and anvils to list of blocks that don't trigger abilities
+ ! Changed Fishing, Shake drops changed from guaranteed to based upon fishing level and perks
+ ! Changed Woodcutting, the amount of experience earned when using Tree Feller on jungle trees has increased
+ ! Changed filesystem usage, it's reduced a lot. Should help reduce lag on larger servers
+ = Fixed Woodcutting bug, excessive null chunk before earning Woodcutting experience
+ = Fixed a null pointer error related to skill cooldowns
+ = Fixed more NPE ?? Needs better explanation
+ - Removed nothing
+
 Version 1.3.11
  ! Changed axes to start with 1 durability damage instead of 5, gain 1 durability damage every 50 levels instead of 30, and only have a 25% chance on hit to damage armor (per armor piece)
  + Added compatibility with bow-wielding NPCs from Citizens/NPC mods

+ 84 - 82
src/main/java/com/gmail/nossr50/commands/skills/AcrobaticsCommand.java

@@ -1,90 +1,92 @@
 package com.gmail.nossr50.commands.skills;
 
+import java.text.DecimalFormat;
+
 import com.gmail.nossr50.commands.SkillCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 
 public class AcrobaticsCommand extends SkillCommand {
-    private String dodgeChance;
-    private String rollChance;
-    private String gracefulRollChance;
-
-    private boolean canDodge;
-    private boolean canRoll;
-    private boolean canGracefulRoll;
-
-    public AcrobaticsCommand() {
-        super(SkillType.ACROBATICS);
-    }
-
-    @Override
-    protected void dataCalculations() {
-        if (skillValue >= 1000) {
-            dodgeChance = "20.00%";
-            rollChance = "100.00%";
-            gracefulRollChance = "100.00%";
-        }
-        else if (skillValue >= 800) {
-            dodgeChance = "20.00%";
-            rollChance = percent.format(skillValue / 1000);
-            gracefulRollChance = "100.00%";
-        }
-        else if (skillValue >= 500) {
-            dodgeChance = percent.format(skillValue / 4000);
-            rollChance = percent.format(skillValue / 1000);
-            gracefulRollChance = "100.00%";
-        }
-        else {
-            dodgeChance = percent.format(skillValue / 4000);
-            rollChance = percent.format(skillValue / 1000);
-            gracefulRollChance = percent.format(skillValue / 500);
-        }
-    }
-
-    @Override
-    protected void permissionsCheck() {
-        canDodge = permInstance.dodge(player);
-        canRoll = permInstance.roll(player);
-        canGracefulRoll = permInstance.gracefulRoll(player);
-    }
-
-    @Override
-    protected boolean effectsHeaderPermissions() {
-        return canDodge || canGracefulRoll || canRoll;
-    }
-
-    @Override
-    protected void effectsDisplay() {
-        if (canRoll) {
-            player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Acrobatics.Effect.0"), LocaleLoader.getString("Acrobatics.Effect.1") }));
-        }
-
-        if (canGracefulRoll) {
-            player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Acrobatics.Effect.2"), LocaleLoader.getString("Acrobatics.Effect.3") }));
-        }
-
-        if (canDodge) {
-            player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Acrobatics.Effect.4"), LocaleLoader.getString("Acrobatics.Effect.5") }));
-        }
-    }
-
-    @Override
-    protected boolean statsHeaderPermissions() {
-        return canDodge || canGracefulRoll || canRoll;
-    }
-
-    @Override
-    protected void statsDisplay() {
-        if (canRoll) {
-            player.sendMessage(LocaleLoader.getString("Acrobatics.Roll.Chance", new Object[] { rollChance }));
-        }
-
-        if (canGracefulRoll) {
-            player.sendMessage(LocaleLoader.getString("Acrobatics.Roll.GraceChance", new Object[] { gracefulRollChance }));
-        }
-
-        if (canDodge) {
-            player.sendMessage(LocaleLoader.getString("Acrobatics.DodgeChance", new Object[] { dodgeChance }));
-        }
-    }
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+
+	private String dodgeChance;
+	private String rollChance;
+	private String gracefulRollChance;
+
+	private float dodgeChanceMax = advancedConfig.getDodgeChanceMax();
+	private float dodgeMaxBonusLevel = advancedConfig.getDodgeMaxBonusLevel();
+	private float rollChanceMax = advancedConfig.getRollChanceMax();
+	private float rollMaxBonusLevel = advancedConfig.getRollMaxBonusLevel();
+	private float gracefulRollChanceMax = advancedConfig.getGracefulRollChanceMax();
+	private float gracefulRollMaxBonusLevel = advancedConfig.getGracefulRollMaxBonusLevel();
+
+	private boolean canDodge;
+	private boolean canRoll;
+	private boolean canGracefulRoll;
+
+	public AcrobaticsCommand() {
+		super(SkillType.ACROBATICS);
+	}
+
+	@Override
+	protected void dataCalculations() {
+		DecimalFormat df = new DecimalFormat("#.0");
+		// DODGE
+		if(skillValue >= dodgeMaxBonusLevel) dodgeChance = df.format(dodgeChanceMax);
+		else dodgeChance = df.format((dodgeChanceMax / dodgeMaxBonusLevel) * skillValue);
+		// ROLL
+		if(skillValue >= rollMaxBonusLevel) rollChance = df.format(rollChanceMax);
+		else rollChance = df.format((rollChanceMax / rollMaxBonusLevel) * skillValue);			
+		// GRACEFULROLL
+		if(skillValue >= gracefulRollMaxBonusLevel) gracefulRollChance = df.format(gracefulRollChanceMax);
+		else gracefulRollChance = df.format((gracefulRollChanceMax / gracefulRollMaxBonusLevel) * skillValue);
+	}
+
+	@Override
+	protected void permissionsCheck() {
+		canDodge = permInstance.dodge(player);
+		canRoll = permInstance.roll(player);
+		canGracefulRoll = permInstance.gracefulRoll(player);
+	}
+
+	@Override
+	protected boolean effectsHeaderPermissions() {
+		return canDodge || canGracefulRoll || canRoll;
+	}
+
+	@Override
+	protected void effectsDisplay() {
+		if (canRoll) {
+			player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Acrobatics.Effect.0"), LocaleLoader.getString("Acrobatics.Effect.1") }));
+		}
+
+		if (canGracefulRoll) {
+			player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Acrobatics.Effect.2"), LocaleLoader.getString("Acrobatics.Effect.3") }));
+		}
+
+		if (canDodge) {
+			player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Acrobatics.Effect.4"), LocaleLoader.getString("Acrobatics.Effect.5") }));
+		}
+	}
+
+	@Override
+	protected boolean statsHeaderPermissions() {
+		return canDodge || canGracefulRoll || canRoll;
+	}
+
+	@Override
+	protected void statsDisplay() {
+		if (canRoll) {
+			player.sendMessage(LocaleLoader.getString("Acrobatics.Roll.Chance", new Object[] { rollChance }));
+		}
+
+		if (canGracefulRoll) {
+			player.sendMessage(LocaleLoader.getString("Acrobatics.Roll.GraceChance", new Object[] { gracefulRollChance }));
+		}
+
+		if (canDodge) {
+			player.sendMessage(LocaleLoader.getString("Acrobatics.DodgeChance", new Object[] { dodgeChance }));
+		}
+	}
 }

+ 91 - 72
src/main/java/com/gmail/nossr50/commands/skills/ArcheryCommand.java

@@ -1,80 +1,99 @@
 package com.gmail.nossr50.commands.skills;
 
+import java.text.DecimalFormat;
+
 import com.gmail.nossr50.commands.SkillCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 
 public class ArcheryCommand extends SkillCommand {
-    private String skillShotBonus;
-    private String dazeChance;
-    private String retrieveChance;
-
-    private boolean canSkillShot;
-    private boolean canDaze;
-    private boolean canRetrieve;
-
-    public ArcheryCommand() {
-        super(SkillType.ARCHERY);
-    }
-
-    @Override
-    protected void dataCalculations() {
-        if (skillValue >= 1000) {
-            skillShotBonus = "200.00%";
-            dazeChance = "50.00%";
-            retrieveChance = "100.00%";
-        }
-        else {
-            skillShotBonus = percent.format(((int) skillValue / 50) * 0.1D); //TODO: Not sure if this is the best way to calculate this or not...
-            dazeChance = percent.format(skillValue / 2000);
-            retrieveChance = percent.format(skillValue / 1000);
-        }
-    }
-
-    @Override
-    protected void permissionsCheck() {
-        canSkillShot = permInstance.archeryBonus(player);
-        canDaze = permInstance.daze(player);
-        canRetrieve = permInstance.trackArrows(player);
-    }
-
-    @Override
-    protected boolean effectsHeaderPermissions() {
-        return canSkillShot || canDaze || canRetrieve;
-    }
-
-    @Override
-    protected void effectsDisplay() {
-        if (canSkillShot) {
-            player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Archery.Effect.0"), LocaleLoader.getString("Archery.Effect.1") }));
-        }
-
-        if (canDaze) {
-            player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Archery.Effect.2"), LocaleLoader.getString("Archery.Effect.3") }));
-        }
-
-        if (canRetrieve) {
-            player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Archery.Effect.4"), LocaleLoader.getString("Archery.Effect.5") }));
-        }
-    }
-
-    @Override
-    protected boolean statsHeaderPermissions() {
-        return canSkillShot || canDaze || canRetrieve;
-    }
-
-    @Override
-    protected void statsDisplay() {
-        if (canSkillShot) {
-            player.sendMessage(LocaleLoader.getString("Archery.Combat.SkillshotBonus", new Object[] { skillShotBonus }));
-        }
-
-        if (canDaze) {
-            player.sendMessage(LocaleLoader.getString("Archery.Combat.DazeChance", new Object[] { dazeChance }));
-        }
-
-        if (canRetrieve) {
-            player.sendMessage(LocaleLoader.getString("Archery.Combat.RetrieveChance", new Object[] { retrieveChance }));
-        }
-    }
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+
+	private String skillShotBonus;
+	private String dazeChance;
+	private String retrieveChance;
+
+	private int skillShotIncreaseLevel = advancedConfig.getSkillShotIncreaseLevel();
+	private double skillShotIncreasePercentage = advancedConfig.getSkillShotIncreasePercentage();
+	private double skillShotBonusMax = advancedConfig.getSkillShotBonusMax();
+
+	private float dazeBonusMax = advancedConfig.getDazeBonusMax();
+	private float dazeMaxBonusLevel = advancedConfig.getDazeMaxBonusLevel();
+
+	private float retrieveBonusMax = advancedConfig.getRetrieveBonusMax();
+	private float retrieveMaxBonusLevel = advancedConfig.getRetrieveMaxBonusLevel();
+
+
+	private boolean canSkillShot;
+	private boolean canDaze;
+	private boolean canRetrieve;
+
+	public ArcheryCommand() {
+		super(SkillType.ARCHERY);
+	}
+
+	@Override
+	protected void dataCalculations() {
+		DecimalFormat df = new DecimalFormat("#.0");
+		// SkillShot
+        double bonus = (int)(skillValue / skillShotIncreaseLevel) * skillShotIncreasePercentage;
+        if (bonus > skillShotBonusMax) skillShotBonus = percent.format(skillShotBonusMax);
+        else skillShotBonus = percent.format(bonus);
+        
+		// Daze
+		if(skillValue >= dazeMaxBonusLevel) dazeChance = df.format(dazeBonusMax);
+		else dazeChance = df.format((dazeBonusMax / dazeMaxBonusLevel) * skillValue);
+
+		// Retrieve
+		if(skillValue >= retrieveMaxBonusLevel)	retrieveChance = df.format(retrieveBonusMax);
+		else retrieveChance = df.format((retrieveBonusMax / retrieveMaxBonusLevel) * skillValue);
+	}
+
+	@Override
+	protected void permissionsCheck() {
+		canSkillShot = permInstance.archeryBonus(player);
+		canDaze = permInstance.daze(player);
+		canRetrieve = permInstance.trackArrows(player);
+	}
+
+	@Override
+	protected boolean effectsHeaderPermissions() {
+		return canSkillShot || canDaze || canRetrieve;
+	}
+
+	@Override
+	protected void effectsDisplay() {
+		if (canSkillShot) {
+			player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Archery.Effect.0"), LocaleLoader.getString("Archery.Effect.1") }));
+		}
+
+		if (canDaze) {
+			player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Archery.Effect.2"), LocaleLoader.getString("Archery.Effect.3") }));
+		}
+
+		if (canRetrieve) {
+			player.sendMessage(LocaleLoader.getString("Effects.Template", new Object[] { LocaleLoader.getString("Archery.Effect.4"), LocaleLoader.getString("Archery.Effect.5") }));
+		}
+	}
+
+	@Override
+	protected boolean statsHeaderPermissions() {
+		return canSkillShot || canDaze || canRetrieve;
+	}
+
+	@Override
+	protected void statsDisplay() {
+		if (canSkillShot) {
+			player.sendMessage(LocaleLoader.getString("Archery.Combat.SkillshotBonus", new Object[] { skillShotBonus }));
+		}
+
+		if (canDaze) {
+			player.sendMessage(LocaleLoader.getString("Archery.Combat.DazeChance", new Object[] { dazeChance }));
+		}
+
+		if (canRetrieve) {
+			player.sendMessage(LocaleLoader.getString("Archery.Combat.RetrieveChance", new Object[] { retrieveChance }));
+		}
+	}
 }

+ 24 - 15
src/main/java/com/gmail/nossr50/commands/skills/AxesCommand.java

@@ -1,16 +1,30 @@
 package com.gmail.nossr50.commands.skills;
 
+import java.text.DecimalFormat;
+
 import com.gmail.nossr50.commands.SkillCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.util.Misc;
 
 public class AxesCommand extends SkillCommand {
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+	
     private String critChance;
     private String bonusDamage;
     private String impactDamage;
     private String greaterImpactDamage;
     private String skullSplitterLength;
 
+	private int bonusDamageAxesBonusMax = advancedConfig.getBonusDamageAxesBonusMax();
+	private int bonusDamageAxesMaxBonusLevel = advancedConfig.getBonusDamageAxesMaxBonusLevel();
+	private double critMaxChance = advancedConfig.getAxesCriticalChance();
+	private int critMaxBonusLevel = advancedConfig.getAxesCriticalMaxBonusLevel();
+	private int greaterImpactIncreaseLevel = advancedConfig.getGreaterImpactIncreaseLevel();
+//	private double greaterImpactModifier = advancedConfig.getGreaterImpactModifier();
+	private int abilityLengthIncreaseLevel = advancedConfig.getAbilityLength();
+
     private boolean canSkullSplitter;
     private boolean canCritical;
     private boolean canBonusDamage;
@@ -23,22 +37,17 @@ public class AxesCommand extends SkillCommand {
 
     @Override
     protected void dataCalculations() {
-        impactDamage = String.valueOf(1 + ((int) skillValue / 50));
-        skullSplitterLength = String.valueOf(2 + ((int) skillValue / 50));
-        greaterImpactDamage = "2";
+    	DecimalFormat df = new DecimalFormat("#.0");
+    	int skillCheck = Misc.skillCheck((int)skillValue, critMaxBonusLevel);
 
-        if (skillValue >= 750) {
-            critChance = "37.50";
-            bonusDamage = "4";
-        }
-        else if (skillValue >= 200) {
-            critChance = percent.format(skillValue / 2000);
-            bonusDamage = "4";
-        }
-        else {
-            critChance = percent.format(skillValue / 2000);
-            bonusDamage = String.valueOf((int) skillValue / 50);
-        }
+    	impactDamage = String.valueOf(1 + ((int) skillValue / greaterImpactIncreaseLevel));
+    	skullSplitterLength = String.valueOf(2 + ((int) skillValue / abilityLengthIncreaseLevel));
+    	greaterImpactDamage = "2";
+
+    	if (skillValue >= critMaxBonusLevel) critChance = df.format(critMaxChance);
+    	else critChance = String.valueOf((critMaxChance / critMaxBonusLevel) * (float)skillCheck);
+    	if (skillValue >= bonusDamageAxesMaxBonusLevel) bonusDamage = String.valueOf(bonusDamageAxesBonusMax);
+    	else bonusDamage = String.valueOf((int) skillValue / (bonusDamageAxesMaxBonusLevel / bonusDamageAxesBonusMax));
     }
 
     @Override

+ 5 - 1
src/main/java/com/gmail/nossr50/commands/skills/ExcavationCommand.java

@@ -1,12 +1,16 @@
 package com.gmail.nossr50.commands.skills;
 
 import com.gmail.nossr50.commands.SkillCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 
 public class ExcavationCommand extends SkillCommand {
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
     private String gigaDrillBreakerLength;
 
+    private int abilityLengthIncreaseLevel = advancedConfig.getAbilityLength();
+
     private boolean canGigaDrill;
     private boolean canTreasureHunt;
 
@@ -16,7 +20,7 @@ public class ExcavationCommand extends SkillCommand {
 
     @Override
     protected void dataCalculations() {
-        gigaDrillBreakerLength = String.valueOf(2 + ((int) skillValue / 50));
+        gigaDrillBreakerLength = String.valueOf(2 + ((int) skillValue / abilityLengthIncreaseLevel));
     }
 
     @Override

+ 8 - 3
src/main/java/com/gmail/nossr50/commands/skills/FishingCommand.java

@@ -1,14 +1,18 @@
 package com.gmail.nossr50.commands.skills;
 
 import com.gmail.nossr50.commands.SkillCommand;
-import com.gmail.nossr50.config.Config;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.gathering.Fishing;
 
 public class FishingCommand extends SkillCommand {
+
+    AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+    
     private int lootTier;
     private String magicChance;
+    private int shakeUnlockLevel;
     private String shakeChance;
 
     private boolean canTreasureHunt;
@@ -23,6 +27,7 @@ public class FishingCommand extends SkillCommand {
     protected void dataCalculations() {
         lootTier = Fishing.getFishingLootTier(profile);
         magicChance = percent.format((float) lootTier / 15);
+        shakeUnlockLevel = advancedConfig.getShakeUnlockLevel();
         shakeChance = String.valueOf(Fishing.getShakeChance(lootTier));
     }
 
@@ -69,8 +74,8 @@ public class FishingCommand extends SkillCommand {
         }
 
         if (canShake) {
-            if (skillValue < 150) {
-                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Fishing.Ability.Locked.0") }));
+            if (skillValue < advancedConfig.getShakeUnlockLevel()) {
+                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Fishing.Ability.Locked.0", new Object[] { shakeUnlockLevel }) }));
             }
             else {
                 player.sendMessage(LocaleLoader.getString("Fishing.Ability.Shake", new Object[] { shakeChance }));

+ 30 - 44
src/main/java/com/gmail/nossr50/commands/skills/HerbalismCommand.java

@@ -1,17 +1,32 @@
 package com.gmail.nossr50.commands.skills;
 
+import java.text.DecimalFormat;
+
 import com.gmail.nossr50.commands.SkillCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 
 public class HerbalismCommand extends SkillCommand {
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+	
     private String greenTerraLength;
     private String greenThumbChance;
     private String greenThumbStage;
     private String farmersDietRank;
     private String doubleDropChance;
 
+    private int abilityLengthIncreaseLevel = advancedConfig.getAbilityLength();
+    private int farmersDietRankChange = advancedConfig.getFarmerDietRankChange();
+    private int farmersDietMaxLevel = farmersDietRankChange * 5;
+    private int greenThumbStageChange = advancedConfig.getGreenThumbStageChange();
+    private int greenThumbStageMaxLevel = greenThumbStageChange * 4;
+    private double greenThumbMaxBonus = advancedConfig.getGreenThumbChanceMax();
+    private int greenThumbMaxLevel = advancedConfig.getGreenThumbMaxLevel();
+    private double doubleDropsMaxBonus = advancedConfig.getHerbalismDoubleDropsChanceMax();
+    private int doubleDropsMaxLevel = advancedConfig.getHerbalismDoubleDropsMaxLevel();
+	
     private boolean canGreenTerra;
     private boolean canGreenThumbWheat;
     private boolean canGreenThumbBlocks;
@@ -25,50 +40,21 @@ public class HerbalismCommand extends SkillCommand {
 
     @Override
     protected void dataCalculations() {
-        greenTerraLength = String.valueOf(2 + ((int) skillValue / 50));
-
-        if (skillValue >= 1500) {
-            greenThumbChance = "100.00%";
-            greenThumbStage = "4";
-            farmersDietRank = "5";
-            doubleDropChance = "100.00%";
-        }
-        else if (skillValue >= 1000) {
-            greenThumbChance = percent.format(skillValue / 1500);
-            greenThumbStage = "4";
-            farmersDietRank = "5";
-            doubleDropChance = "100.00%";
-        }
-        else if (skillValue >= 800) {
-            greenThumbChance = percent.format(skillValue / 1500);
-            greenThumbStage = "4";
-            farmersDietRank = "4";
-            doubleDropChance = percent.format(skillValue / 1000);
-        }
-        else if (skillValue >= 600) {
-            greenThumbChance = percent.format(skillValue / 1500);
-            greenThumbStage = "4";
-            farmersDietRank = "3";
-            doubleDropChance = percent.format(skillValue / 1000);
-        }
-        else if (skillValue >= 400) {
-            greenThumbChance = percent.format(skillValue / 1500);
-            greenThumbStage = "3";
-            farmersDietRank = "2";
-            doubleDropChance = percent.format(skillValue / 1000);
-        }
-        else if (skillValue >= 200) {
-            greenThumbChance = percent.format(skillValue / 1500);
-            greenThumbStage = "2";
-            farmersDietRank = "1";
-            doubleDropChance = percent.format(skillValue / 1000);
-        }
-        else {
-            greenThumbChance = percent.format(skillValue / 1500);
-            greenThumbStage = "1";
-            farmersDietRank = "1";
-            doubleDropChance = percent.format(skillValue / 1000);
-        }
+    	DecimalFormat df = new DecimalFormat("#.0");
+    	greenTerraLength = String.valueOf(2 + ((int) skillValue / abilityLengthIncreaseLevel));
+    	//FARMERS DIET
+    	if(skillValue >= farmersDietMaxLevel) farmersDietRank = "5";
+    	else farmersDietRank = String.valueOf((int)skillValue / farmersDietRankChange);
+    	//GREEN THUMB
+    	if(skillValue >= greenThumbStageMaxLevel) greenThumbStage = "4";
+    	else greenThumbStage = String.valueOf((int)skillValue / greenThumbStageChange);
+    	
+    	
+    	if(skillValue >= greenThumbMaxLevel) greenThumbChance = String.valueOf(greenThumbMaxBonus);
+    	else greenThumbChance = String.valueOf((greenThumbMaxBonus / greenThumbMaxLevel) * skillValue);
+    	//DOUBLE DROPS
+    	if(skillValue >= doubleDropsMaxLevel) doubleDropChance = df.format(doubleDropsMaxBonus);
+    	else doubleDropChance = df.format((doubleDropsMaxBonus / doubleDropsMaxLevel) * skillValue);
     }
 
     @Override

+ 36 - 25
src/main/java/com/gmail/nossr50/commands/skills/MiningCommand.java

@@ -1,18 +1,35 @@
 package com.gmail.nossr50.commands.skills;
 
+import java.text.DecimalFormat;
+
 import com.gmail.nossr50.commands.SkillCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.Misc;
 
 public class MiningCommand extends SkillCommand {
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
     private String doubleDropChance;
     private String superBreakerLength;
     private String blastMiningRank;
     private String blastRadiusIncrease;
     private String blastDamageDecrease;
 
+	private int blastMiningRank1 = advancedConfig.getBlastMiningRank1();
+	private int blastMiningRank2 = advancedConfig.getBlastMiningRank2();
+	private int blastMiningRank3 = advancedConfig.getBlastMiningRank3();
+	private int blastMiningRank4 = advancedConfig.getBlastMiningRank4();
+	private int blastMiningRank5 = advancedConfig.getBlastMiningRank5();
+	private int blastMiningRank6 = advancedConfig.getBlastMiningRank6();
+	private int blastMiningRank7 = advancedConfig.getBlastMiningRank7();
+	private int blastMiningRank8 = advancedConfig.getBlastMiningRank8();
+
+	private double doubleDropsMaxBonus = advancedConfig.getMiningDoubleDropChance();
+	private int doubleDropsMaxLevel = advancedConfig.getMiningDoubleDropMaxLevel();
+	public int abilityLengthIncreaseLevel = advancedConfig.getAbilityLength();
+
     private boolean canSuperBreaker;
     private boolean canDoubleDrop;
     private boolean canBlast;
@@ -26,61 +43,55 @@ public class MiningCommand extends SkillCommand {
 
     @Override
     protected void dataCalculations() {
-        superBreakerLength = String.valueOf(2 + ((int) skillValue / 50));
-
-        if (skillValue >= 1000) {
+    	DecimalFormat df = new DecimalFormat("#.0");
+        superBreakerLength = String.valueOf(2 + ((int) skillValue / abilityLengthIncreaseLevel));
+    	if(skillValue >= doubleDropsMaxLevel) doubleDropChance = df.format(doubleDropsMaxBonus);
+    	else doubleDropChance = df.format((doubleDropsMaxBonus / doubleDropsMaxLevel) * skillValue);
+        
+        if (skillValue >= blastMiningRank8) {
             blastMiningRank = "8";
             blastDamageDecrease = "100.00%";
             blastRadiusIncrease = "4";
-            doubleDropChance = "100.00%";
         }
-        else if (skillValue >= 875) {
+        else if (skillValue >= blastMiningRank7) {
             blastMiningRank = "7";
             blastDamageDecrease = "50.00%";
             blastRadiusIncrease = "3";
-            doubleDropChance = percent.format(skillValue / 1000);
         }
-        else if (skillValue >= 750) {
+        else if (skillValue >= blastMiningRank6) {
             blastMiningRank = "6";
             blastDamageDecrease = "50.00%";
             blastRadiusIncrease = "3";
-            doubleDropChance = percent.format(skillValue / 1000);
         }
-        else if (skillValue >= 625) {
+        else if (skillValue >= blastMiningRank5) {
             blastMiningRank = "5";
             blastDamageDecrease = "25.00%";
             blastRadiusIncrease = "2";
-            doubleDropChance = percent.format(skillValue / 1000);
         }
-        else if (skillValue >= 500) {
+        else if (skillValue >= blastMiningRank4) {
             blastMiningRank = "4";
             blastDamageDecrease = "25.00%";
             blastRadiusIncrease = "2";
-            doubleDropChance = percent.format(skillValue / 1000);
         }
-        else if (skillValue >= 375) {
+        else if (skillValue >= blastMiningRank3) {
             blastMiningRank = "3";
             blastDamageDecrease = "0.00%";
             blastRadiusIncrease = "1";
-            doubleDropChance = percent.format(skillValue / 1000);
         }
-        else if (skillValue >= 250) {
+        else if (skillValue >= blastMiningRank2) {
             blastMiningRank = "2";
             blastDamageDecrease = "0.00%";
             blastRadiusIncrease = "1";
-            doubleDropChance = percent.format(skillValue / 1000);
         }
-        else if (skillValue >= 125) {
+        else if (skillValue >= blastMiningRank1) {
             blastMiningRank = "1";
             blastDamageDecrease = "0.00%";
             blastRadiusIncrease = "0";
-            doubleDropChance = percent.format(skillValue / 1000);
         }
         else {
             blastMiningRank = "0";
             blastDamageDecrease = "0.00%";
             blastRadiusIncrease = "0";
-            doubleDropChance = percent.format(skillValue / 1000);
         }
     }
 
@@ -140,8 +151,8 @@ public class MiningCommand extends SkillCommand {
         }
 
         if (canBlast) {
-            if (skillValue < 125) {
-                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.0") }));
+            if (skillValue < blastMiningRank1) {
+                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.0", new Object[] { blastMiningRank1 })  }));
             }
             else {
                 player.sendMessage(LocaleLoader.getString("Mining.Blast.Rank", new Object[] { blastMiningRank, LocaleLoader.getString("Mining.Blast.Effect." + (Misc.getInt(blastMiningRank) - 1)) }));
@@ -149,8 +160,8 @@ public class MiningCommand extends SkillCommand {
         }
 
         if (canBiggerBombs) {
-            if (skillValue < 250) {
-                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.1") }));
+            if (skillValue < blastMiningRank2) {
+                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.1", new Object[] { blastMiningRank2 }) }));
             }
             else {
                 player.sendMessage(LocaleLoader.getString("Mining.Blast.Radius.Increase", new Object[] { blastRadiusIncrease }));
@@ -158,8 +169,8 @@ public class MiningCommand extends SkillCommand {
         }
 
         if (canDemoExpert) {
-            if (skillValue < 500) {
-                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.2") }));
+            if (skillValue < blastMiningRank4) {
+                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Mining.Ability.Locked.2", new Object[] { blastMiningRank4 }) }));
             }
             else {
                 player.sendMessage(LocaleLoader.getString("Mining.Effect.Decrease", new Object[] { blastDamageDecrease }));

+ 15 - 8
src/main/java/com/gmail/nossr50/commands/skills/RepairCommand.java

@@ -1,7 +1,10 @@
 package com.gmail.nossr50.commands.skills;
 
+import java.text.DecimalFormat;
+
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.commands.SkillCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
@@ -9,10 +12,16 @@ import com.gmail.nossr50.skills.repair.Repair;
 import com.gmail.nossr50.skills.repair.Repairable;
 
 public class RepairCommand extends SkillCommand {
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
     private int arcaneForgingRank;
     private String repairMasteryBonus;
     private String superRepairChance;
 
+	private float repairMasteryChanceMax = advancedConfig.getRepairMasteryChanceMax();
+	private float repairMasteryMaxBonusLevel = advancedConfig.getRepairMasteryMaxLevel();
+	private float superRepairChanceMax = advancedConfig.getSuperRepairChanceMax();
+	private float superRepairMaxBonusLevel = advancedConfig.getSuperRepairMaxLevel();
+
     private boolean canSuperRepair;
     private boolean canMasterRepair;
     private boolean canArcaneForge;
@@ -37,6 +46,7 @@ public class RepairCommand extends SkillCommand {
 
     @Override
     protected void dataCalculations() {
+		DecimalFormat df = new DecimalFormat("#.0");
         // We're using pickaxes here, not the best but it works
         Repairable diamondRepairable = mcMMO.repairManager.getRepairable(278);
         Repairable goldRepairable = mcMMO.repairManager.getRepairable(285);
@@ -47,17 +57,14 @@ public class RepairCommand extends SkillCommand {
         goldLevel = (goldRepairable == null) ? 0 : goldRepairable.getMinimumLevel();
         ironLevel = (ironRepairable == null) ? 0 : ironRepairable.getMinimumLevel();
         stoneLevel = (stoneRepairable == null) ? 0 : stoneRepairable.getMinimumLevel();
-        
+
         salvageLevel = Config.getInstance().getSalvageUnlockLevel();
 
-        repairMasteryBonus = percent.format(skillValue / 500);
+        if(skillValue >= repairMasteryMaxBonusLevel) repairMasteryBonus = df.format(repairMasteryChanceMax);
+		else repairMasteryBonus = df.format((repairMasteryChanceMax / repairMasteryMaxBonusLevel) * skillValue);
 
-        if (skillValue >= 1000) {
-            superRepairChance = "100.00%";
-        }
-        else {
-            superRepairChance = percent.format(skillValue / 1000);
-        }
+        if(skillValue >= superRepairMaxBonusLevel) superRepairChance = df.format(superRepairChanceMax);
+		else superRepairChance = df.format((superRepairChanceMax / superRepairMaxBonusLevel) * skillValue);
 
         arcaneForgingRank = Repair.getArcaneForgingRank(profile);
     }

+ 26 - 16
src/main/java/com/gmail/nossr50/commands/skills/SwordsCommand.java

@@ -1,15 +1,29 @@
 package com.gmail.nossr50.commands.skills;
 
+import java.text.DecimalFormat;
+
 import com.gmail.nossr50.commands.SkillCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 
 public class SwordsCommand extends SkillCommand {
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+	
     private String counterAttackChance;
     private String bleedLength;
     private String bleedChance;
     private String serratedStrikesLength;
 
+    private int abilityLengthIncreaseLevel = advancedConfig.getAbilityLength();
+    private float bleedChanceMax = advancedConfig.getBleedChanceMax();
+    private float bleedMaxLevel = advancedConfig.getBleedMaxBonusLevel();
+    private int bleedMaxTicks = advancedConfig.getBleedMaxTicks();
+    private int bleedBaseTicks = advancedConfig.getBleedBaseTicks();
+    private float counterChanceMax = advancedConfig.getCounterChanceMax();
+    private float counterMaxLevel = advancedConfig.getCounterMaxBonusLevel();
+    private int serratedBleedTicks = advancedConfig.getSerratedStrikesTicks();
+
     private boolean canCounter;
     private boolean canSerratedStrike;
     private boolean canBleed;
@@ -20,23 +34,19 @@ public class SwordsCommand extends SkillCommand {
 
     @Override
     protected void dataCalculations() {
-        serratedStrikesLength = String.valueOf(2 + ((int) skillValue / 50));
+		DecimalFormat df = new DecimalFormat("#.0");
+        serratedStrikesLength = String.valueOf(2 + ((int) skillValue / abilityLengthIncreaseLevel));
+        
+        if (skillValue >= bleedMaxLevel) bleedLength = String.valueOf(bleedMaxTicks);
+        else bleedLength = String.valueOf(bleedBaseTicks);
 
-        if (skillValue >= 750) {
-            bleedLength = "3";
-            bleedChance = "75.00%";
-            counterAttackChance = "30.00%";
-        }
-        else if (skillValue >= 600) {
-            bleedLength = "2";
-            bleedChance = percent.format(skillValue / 1000);
-            counterAttackChance = "30.00%";
-        }
-        else {
-            bleedLength = "2";
-            bleedChance = percent.format(skillValue / 1000);
-            counterAttackChance = percent.format(skillValue / 2000);
-        }
+		if(skillValue >= bleedMaxLevel) bleedChance = df.format(bleedChanceMax);
+		else bleedChance = df.format((bleedChanceMax / bleedMaxLevel) * skillValue);
+        
+		if(skillValue >= counterMaxLevel) counterAttackChance = df.format(counterChanceMax);
+		else counterAttackChance = df.format((counterChanceMax / counterMaxLevel) * skillValue);
+		
+		serratedStrikesLength = String.valueOf(serratedBleedTicks);
     }
 
     @Override

+ 28 - 17
src/main/java/com/gmail/nossr50/commands/skills/TamingCommand.java

@@ -1,13 +1,26 @@
 package com.gmail.nossr50.commands.skills;
 
+import java.text.DecimalFormat;
+
 import com.gmail.nossr50.commands.SkillCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 
 public class TamingCommand extends SkillCommand {
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
     private String goreChance;
 
+	private float goreChanceMax = advancedConfig.getGoreChanceMax();
+	private float goreMaxLevel = advancedConfig.getGoreMaxBonusLevel();
+	private int fastFoodUnlock = advancedConfig.getFastFoodUnlock();
+	private float fastFoodChance = advancedConfig.getFastFoodChance();
+	private int enviromentallyAwareUnlock = advancedConfig.getEnviromentallyAwareUnlock();
+	private int thickFurUnlock = advancedConfig.getThickFurUnlock();
+	private int shockProofUnlock = advancedConfig.getShockProofUnlock();
+	private int sharpenedClawUnlock = advancedConfig.getSharpenedClawsUnlock();
+   
     private boolean canBeastLore;
     private boolean canGore;
     private boolean canSharpenedClaws;
@@ -23,12 +36,10 @@ public class TamingCommand extends SkillCommand {
 
     @Override
     protected void dataCalculations() {
-        if (skillValue >= 1000) {
-            goreChance = "100.00%";
-        }
-        else {
-            goreChance = percent.format(skillValue / 1000);
-        }    }
+    	DecimalFormat df = new DecimalFormat("#.0");
+    	if(skillValue >= goreMaxLevel) goreChance = df.format(goreChanceMax);
+    	else goreChance = df.format((goreChanceMax / goreMaxLevel) * skillValue);
+    }    
 
     @Override
     protected void permissionsCheck() {
@@ -94,17 +105,17 @@ public class TamingCommand extends SkillCommand {
     @Override
     protected void statsDisplay() {
         if (canFastFood) {
-            if (skillValue < 50) {
-                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Taming.Ability.Locked.4") }));
+            if (skillValue < fastFoodUnlock) {
+                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Taming.Ability.Locked.4", new Object[] { fastFoodUnlock } ) }));
             }
             else {
-                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template", new Object[] { LocaleLoader.getString("Taming.Ability.Bonus.8"), LocaleLoader.getString("Taming.Ability.Bonus.9") }));
+                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template", new Object[] { LocaleLoader.getString("Taming.Ability.Bonus.8"), LocaleLoader.getString("Taming.Ability.Bonus.9", new Object[] { fastFoodChance } ) }));
             }
         }
 
         if (canEnvironmentallyAware) {
-            if (skillValue < 100) {
-                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Taming.Ability.Locked.0") }));
+            if (skillValue < enviromentallyAwareUnlock) {
+                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Taming.Ability.Locked.0", new Object[] { enviromentallyAwareUnlock } ) }));
             }
             else {
                 player.sendMessage(LocaleLoader.getString("Ability.Generic.Template", new Object[] { LocaleLoader.getString("Taming.Ability.Bonus.0"), LocaleLoader.getString("Taming.Ability.Bonus.1") }));
@@ -112,8 +123,8 @@ public class TamingCommand extends SkillCommand {
         }
 
         if (canThickFur) {
-            if (skillValue < 250) {
-                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Taming.Ability.Locked.1") }));
+            if (skillValue < thickFurUnlock) {
+                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Taming.Ability.Locked.1", new Object[] { thickFurUnlock } ) }));
             }
             else {
                 player.sendMessage(LocaleLoader.getString("Ability.Generic.Template", new Object[] { LocaleLoader.getString("Taming.Ability.Bonus.2"), LocaleLoader.getString("Taming.Ability.Bonus.3") }));
@@ -121,8 +132,8 @@ public class TamingCommand extends SkillCommand {
         }
 
         if (canShockProof) {
-            if (skillValue < 500) {
-                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Taming.Ability.Locked.2") }));
+            if (skillValue < shockProofUnlock) {
+                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Taming.Ability.Locked.2", new Object[] { shockProofUnlock } ) }));
             }
             else {
                 player.sendMessage(LocaleLoader.getString("Ability.Generic.Template", new Object[] { LocaleLoader.getString("Taming.Ability.Bonus.4"), LocaleLoader.getString("Taming.Ability.Bonus.5") }));
@@ -130,8 +141,8 @@ public class TamingCommand extends SkillCommand {
         }
 
         if (canSharpenedClaws) {
-            if (skillValue < 750) {
-                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Taming.Ability.Locked.3") }));
+            if (skillValue < sharpenedClawUnlock) {
+                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Taming.Ability.Locked.3", new Object[] { sharpenedClawUnlock } ) }));
             }
             else {
                 player.sendMessage(LocaleLoader.getString("Ability.Generic.Template", new Object[] { LocaleLoader.getString("Taming.Ability.Bonus.6"), LocaleLoader.getString("Taming.Ability.Bonus.7") }));

+ 23 - 16
src/main/java/com/gmail/nossr50/commands/skills/UnarmedCommand.java

@@ -1,15 +1,27 @@
 package com.gmail.nossr50.commands.skills;
 
+import java.text.DecimalFormat;
+
 import com.gmail.nossr50.commands.SkillCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 
 public class UnarmedCommand extends SkillCommand {
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
     private String berserkLength;
     private String deflectChance;
     private String disarmChance;
     private String ironArmBonus;
 
+    private float disarmChanceMax = advancedConfig.getDisarmChanceMax();
+    private float disarmMaxLevel = advancedConfig.getDisarmMaxBonusLevel();
+    private float deflectChanceMax = advancedConfig.getDeflectChanceMax();
+    private float deflectMaxLevel = advancedConfig.getDeflectMaxBonusLevel();
+    private float ironArmMaxBonus = advancedConfig.getIronArmBonus();
+    private int ironArmIncreaseLevel = advancedConfig.getIronArmIncreaseLevel();
+	private int abilityLengthIncreaseLevel = advancedConfig.getAbilityLength();
+
     private boolean canBerserk;
     private boolean canDisarm;
     private boolean canBonusDamage;
@@ -21,23 +33,18 @@ public class UnarmedCommand extends SkillCommand {
 
     @Override
     protected void dataCalculations() {
-        berserkLength = String.valueOf(2 + ((int) skillValue / 50));
+		DecimalFormat df = new DecimalFormat("#.0");
+        berserkLength = String.valueOf(2 + ((int) skillValue / abilityLengthIncreaseLevel));
 
-        if (skillValue >= 1000) {
-            disarmChance = "33.33%";
-            deflectChance = "50.00%";
-            ironArmBonus = "8";
-        }
-        else if (skillValue >= 250) {
-            disarmChance = percent.format(skillValue / 3000);
-            deflectChance = percent.format(skillValue / 2000);
-            ironArmBonus = "8";
-        }
-        else {
-            disarmChance = percent.format(skillValue / 3000);
-            deflectChance = percent.format(skillValue / 2000);
-            ironArmBonus = String.valueOf(3 + ((int) skillValue / 50));
-        }    }
+        if(skillValue >= disarmMaxLevel) disarmChance = df.format(disarmChanceMax);
+		else disarmChance = df.format((disarmChanceMax / disarmMaxLevel) * skillValue);
+        
+        if(skillValue >= deflectMaxLevel) deflectChance = df.format(deflectChanceMax);
+        else deflectChance = df.format((deflectChanceMax / deflectMaxLevel) * skillValue);
+
+        if (skillValue >= 250) ironArmBonus = String.valueOf(ironArmMaxBonus);
+        else ironArmBonus = String.valueOf(3 + ((int) skillValue / ironArmIncreaseLevel));
+    }
 
     @Override
     protected void permissionsCheck() {

+ 15 - 9
src/main/java/com/gmail/nossr50/commands/skills/WoodcuttingCommand.java

@@ -1,14 +1,23 @@
 package com.gmail.nossr50.commands.skills;
 
+import java.text.DecimalFormat;
+
 import com.gmail.nossr50.commands.SkillCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 
 public class WoodcuttingCommand extends SkillCommand {
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
     private String treeFellerLength;
     private String doubleDropChance;
 
+	private int abilityLengthIncreaseLevel = advancedConfig.getAbilityLength();
+	private double doubleDropsMaxBonus = advancedConfig.getWoodcuttingDoubleDropChance();
+	private int doubleDropsMaxLevel = advancedConfig.getWoodcuttingDoubleDropMaxLevel();
+	private int leafBlowUnlock = advancedConfig.getLeafBlowUnlockLevel();
+	
     private boolean canTreeFell;
     private boolean canLeafBlow;
     private boolean canDoubleDrop;
@@ -20,14 +29,11 @@ public class WoodcuttingCommand extends SkillCommand {
 
     @Override
     protected void dataCalculations() {
-        treeFellerLength = String.valueOf(2 + ((int) skillValue / 50));
+    	DecimalFormat df = new DecimalFormat("0.0");
 
-        if (skillValue >= 1000) {
-            doubleDropChance = "100.00%";
-        }
-        else {
-            doubleDropChance = percent.format(skillValue / 1000);
-        }
+        treeFellerLength = String.valueOf(2 + ((int) skillValue / abilityLengthIncreaseLevel));
+    	if(skillValue >= doubleDropsMaxLevel) doubleDropChance = df.format(doubleDropsMaxBonus);
+    	else doubleDropChance = df.format((doubleDropsMaxBonus / doubleDropsMaxLevel) * skillValue);
     }
 
     @Override
@@ -69,8 +75,8 @@ public class WoodcuttingCommand extends SkillCommand {
     protected void statsDisplay() {
         //TODO: Remove? Basically duplicates the above.
         if (canLeafBlow) {
-            if (skillValue < 100) {
-                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Woodcutting.Ability.Locked.0") }));
+            if (skillValue < leafBlowUnlock) {
+                player.sendMessage(LocaleLoader.getString("Ability.Generic.Template.Lock", new Object[] { LocaleLoader.getString("Woodcutting.Ability.Locked.0", new Object[] { leafBlowUnlock }) }));
             }
             else {
                 player.sendMessage(LocaleLoader.getString("Ability.Generic.Template", new Object[] { LocaleLoader.getString("Woodcutting.Ability.0"), LocaleLoader.getString("Woodcutting.Ability.1") }));

+ 152 - 0
src/main/java/com/gmail/nossr50/config/AdvancedConfig.java

@@ -0,0 +1,152 @@
+package com.gmail.nossr50.config;
+
+public class AdvancedConfig extends ConfigLoader {
+    private static AdvancedConfig instance;
+    
+    private AdvancedConfig() {
+        super("advanced.yml");
+        loadKeys();
+    }
+    public static AdvancedConfig getInstance() {
+        if (instance == null) {
+            instance = new AdvancedConfig();
+        }
+        return instance;
+    }
+    
+	@Override
+	protected void loadKeys() {
+		// TODO Do I need to use this?
+	}
+	/* GENERAL */
+	public int getAbilityLength() { return config.getInt("Skills.General.Ability_IncreaseLevel", 50); }
+	
+    /* ACROBATICS */
+	public int getDodgeChanceMax() { return config.getInt("Skills.Acrobatics.Dodge_ChanceMax", 20); }
+	public int getDodgeMaxBonusLevel() { return config.getInt("Skills.Acrobatics.Dodge_MaxBonusLevel", 800); }
+	
+	public int getRollChanceMax() { return config.getInt("Skills.Acrobatics.Roll_ChanceMax", 100); }
+	public int getRollMaxBonusLevel() { return config.getInt("Skills.Acrobatics.Roll_MaxBonusLevel", 1000); }
+	
+	public int getGracefulRollChanceMax() { return config.getInt("Skills.Acrobatics.GracefulRoll_ChanceMax", 100); }
+	public int getGracefulRollMaxBonusLevel() { return config.getInt("Skills.Acrobatics.GracefulRoll_MaxBonusLevel", 500); }
+
+	public int getDodgeXPModifier() { return config.getInt("Skills.Acrobatics.Dodge_XP_Modifier", 120); }
+	public int getRollXPModifier() { return config.getInt("Skills.Acrobatics.Roll_XP_Modifier", 80); }
+	public int getFallXPModifier() { return config.getInt("Skills.Acrobatics.Fall_XP_Modifier", 120); }
+	
+    /* ARCHERY */
+	public int getSkillShotIncreaseLevel() { return config.getInt("Skills.Archery.SkillShot_IncreaseLevel", 50); }
+	public double getSkillShotIncreasePercentage() { return config.getDouble("Skills.Archery.SkillShot_IncreasePercentage", 0.1D); }
+	public double getSkillShotBonusMax() { return config.getDouble("Skills.Archery.SkillShot_MaxBonus", 2.0D); }
+
+	public int getDazeBonusMax() { return config.getInt("Skills.Archery.Daze_MaxChance", 50); }
+	public int getDazeMaxBonusLevel() { return config.getInt("Skills.Archery.Daze_MaxBonusLevel", 1000); }
+	public int getDazeModifier() { return config.getInt("Skills.Archery.Daze_BonusDamage", 4); }
+
+	public int getRetrieveBonusMax() { return config.getInt("Skills.Archery.Retrieve_MaxBonus", 100); }
+	public int getRetrieveMaxBonusLevel() { return config.getInt("Skills.Archery.Retrieve_MaxBonusLevel", 1000); }
+	
+    /* AXES */
+	public int getBonusDamageAxesBonusMax() { return config.getInt("Skills.Axes.DamageIncrease_MaxBonus", 4); }
+	public int getBonusDamageAxesMaxBonusLevel() { return config.getInt("Skills.Axes.DamageIncrease_MaxBonusLevel", 200); }
+
+	public double getAxesCriticalChance() { return config.getDouble("Skills.Axes.AxesCritical_MaxChance", 37.50); }
+	public int getAxesCriticalMaxBonusLevel() { return config.getInt("Skills.Axes.AxesCritical_MaxBonusLevel", 750); }
+	public double getAxesCriticalPVPModifier() { return config.getDouble("Skills.Axes.AxesCritical_PVP_Modifier", 1.5); }
+	public int getAxesCriticalPVEModifier() { return config.getInt("Skills.Axes.AxesCritical_PVE_Modifier", 2); }
+	
+	public int getGreaterImpactChance() { return config.getInt("Skills.Axes.GreaterImpact_Chance", 25); }
+	public int getGreaterImpactIncreaseLevel() { return config.getInt("Skills.Axes.GreaterImpact_IncreaseLevel", 50); }
+	public double getGreaterImpactModifier() { return config.getDouble("Skills.Axes.GreaterImpact_KnockbackModifier", 1.5); }
+	public int getGreaterImpactBonusDamage() { return config.getInt("Skills.Axes.GreaterImpact_BonusDamage", 2); }
+	
+    /* EXCAVATION */
+	//Nothing to configure, everything is already configurable in config.yml
+	
+    /* FISHING */
+    public int getShakeUnlockLevel() { return config.getInt("Skills.Fishing.Shake_UnlockLevel", 150); }
+    public int getFishingEnchantmentChance() { return config.getInt("Skills.Fishing.Enchantment_Chance", 10); }
+    
+    /* HERBALISM */
+    public int getFarmerDietRankChange() { return config.getInt("Skills.Herbalism.Food_RankChange", 200); }
+    
+    public int getGreenThumbStageChange() { return config.getInt("Skills.Herbalism.GreenThumb_StageChange", 200); }
+    public int getGreenThumbChanceMax() { return config.getInt("Skills.Herbalism.GreenThumb_ChanceMax", 100); }
+    public int getGreenThumbMaxLevel() { return config.getInt("Skills.Herbalism.GreenThumb_MaxBonusLevel", 1500); }
+    
+    public int getHerbalismDoubleDropsChanceMax() { return config.getInt("Skills.Herbalism.DoubleDrops_ChanceMax", 100); }
+    public int getHerbalismDoubleDropsMaxLevel() { return config.getInt("Skills.Herbalism.DoubleDrops_MaxBonusLevel", 1000); }
+    
+    /* MINING */
+    public int getMiningDoubleDropChance() { return config.getInt("Skills.Mining.DoubleDrops_ChanceMax", 100); }
+    public int getMiningDoubleDropMaxLevel() { return config.getInt("Skills.Mining.DoubleDrops_MaxBonusLevel", 1000); }
+
+    public int getBlastMiningRank1() { return config.getInt("Skills.Mining.BlastMining_Rank1", 125); }
+    public int getBlastMiningRank2() { return config.getInt("Skills.Mining.BlastMining_Rank2", 250); }
+    public int getBlastMiningRank3() { return config.getInt("Skills.Mining.BlastMining_Rank3", 375); }
+    public int getBlastMiningRank4() { return config.getInt("Skills.Mining.BlastMining_Rank4", 500); }
+    public int getBlastMiningRank5() { return config.getInt("Skills.Mining.BlastMining_Rank5", 625); }
+    public int getBlastMiningRank6() { return config.getInt("Skills.Mining.BlastMining_Rank6", 750); }
+    public int getBlastMiningRank7() { return config.getInt("Skills.Mining.BlastMining_Rank7", 875); }
+    public int getBlastMiningRank8() { return config.getInt("Skills.Mining.BlastMining_Rank8", 1000); }
+    /* REPAIR */
+    public int getRepairMasteryChanceMax() { return config.getInt("Skills.Repair.RepairMastery_ChanceMax", 200); }
+    public int getRepairMasteryMaxLevel() { return config.getInt("Skills.Repair.RepairMastery_MaxBonusLevel", 1000); }
+    public int getSuperRepairChanceMax() { return config.getInt("Skills.Repair.SuperRepair_ChanceMax", 100); }
+    public int getSuperRepairMaxLevel() { return config.getInt("Skills.Repair.SuperRepair_MaxBonusLevel", 1000); }
+    
+    /* SWORDS */
+	public int getBleedChanceMax() { return config.getInt("Skills.Sword.Bleed_ChanceMax", 75); }
+	public int getBleedMaxBonusLevel() { return config.getInt("Skills.Sword.Bleed_MaxBonusLevel", 750); }
+	public int getBleedMaxTicks() { return config.getInt("Skills.Sword.Bleed_MaxTicks", 3); }
+	public int getBleedBaseTicks() { return config.getInt("Skills.Sword.Bleed_BaseTicks", 2); }
+
+    public int getCounterChanceMax() { return config.getInt("Skills.Sword.Counter_ChanceMax", 30); }
+	public int getCounterMaxBonusLevel() { return config.getInt("Skills.Sword.Counter_MaxBonusLevel", 600); }
+	public int getCounterModifier() { return config.getInt("Skills.Sword.Counter_DamageModifier", 2); }
+	
+	public int getSerratedStrikesModifier() { return config.getInt("Skills.Sword.SerratedStrikes_DamageModifier", 4); }
+	public int getSerratedStrikesTicks() { return config.getInt("Skills.Sword.SerratedStrikes_BleedTicks", 5); }
+    /* TAMING */
+	public int getGoreChanceMax() { return config.getInt("Skills.Taming.Gore_ChanceMax", 100); }
+	public int getGoreMaxBonusLevel() { return config.getInt("Skills.Taming.Gore_MaxBonusLevel", 1000); }
+	public int getGoreBleedTicks() { return config.getInt("Skills.Taming.Gore_BleedTicks", 2); }
+	public int getGoreModifier() { return config.getInt("Skills.Taming.Gore_Modifier", 2); }
+
+	public int getFastFoodUnlock() { return config.getInt("Skills.Taming.FastFood_UnlockLevel", 50); }
+	public int getFastFoodChance() { return config.getInt("Skills.Taming.FastFood_Chance", 50); }
+	
+	public int getEnviromentallyAwareUnlock() { return config.getInt("Skills.Taming.EnvironmentallyAware_UnlockLevel", 100); }
+
+	public int getThickFurUnlock() { return config.getInt("Skills.Taming.ThickFur_UnlockLevel", 250); }
+	public int getThickFurModifier() { return config.getInt("Skills.Taming.ThickFur_Modifier", 2); }
+	
+	public int getShockProofUnlock() { return config.getInt("Skills.Taming.ShockProof_UnlockLevel", 500); }
+	public int getShockProofModifier() { return config.getInt("Skills.Taming.ShockProof_Modifier", 6); }
+
+	public int getSharpenedClawsUnlock() { return config.getInt("Skills.Taming.SharpenedClaws_UnlockLevel", 750); }
+	public int getSharpenedClawsBonus() { return config.getInt("Skills.Taming.SharpenedClaws_Bonus", 2); }
+    /* UNARMED */
+	public int getDisarmChanceMax() { return config.getInt("Skills.Unarmed.Disarm_ChanceMax", 33); }
+	public int getDisarmMaxBonusLevel() { return config.getInt("Skills.Unarmed.Disarm_MaxBonusLevel", 1000); }
+	public int getDeflectChanceMax() { return config.getInt("Skills.Unarmed.Deflect_ChanceMax", 50); }
+	public int getDeflectMaxBonusLevel() { return config.getInt("Skills.Unarmed.Deflect_MaxBonusLevel", 1000); }
+	public int getIronGripChanceMax() { return config.getInt("Skills.Unarmed.IronGrip_ChanceMax", 100); }
+	public int getIronGripMaxBonusLevel() { return config.getInt("Skills.Unarmed.IronGrip_MaxBonusLevel", 1000); }
+	public int getIronArmBonus() { return config.getInt("Skills.Unarmed.IronArm_Bonus", 8); }
+	public int getIronArmIncreaseLevel() { return config.getInt("Skills.Unarmed.IronArm_IncreaseLevel", 50); }
+    /* WOODCUTTING */
+    public int getLeafBlowUnlockLevel() { return config.getInt("Skills.Woodcutting.LeafBlower_UnlockLevel", 100); }
+    public int getWoodcuttingDoubleDropChance() { return config.getInt("Skills.Woodcutting.DoubleDrops_ChanceMax", 100); }
+    public int getWoodcuttingDoubleDropMaxLevel() { return config.getInt("Skills.Woodcutting.DoubleDrops_MaxBonusLevel", 1000); }
+    
+    /* SPOUT STUFF*/
+	public int getSpoutNotificationTier1() { return config.getInt("Spout.Notifications.Tier1", 200); }
+	public int getSpoutNotificationTier2() { return config.getInt("Spout.Notifications.Tier2", 400); }
+	public int getSpoutNotificationTier3() { return config.getInt("Spout.Notifications.Tier3", 600); }
+	public int getSpoutNotificationTier4() { return config.getInt("Spout.Notifications.Tier4", 800); }
+	//TODO Make the sounds configurable! :D
+//	public String getSpoutSoundRepair() { return config.getString("Spout.Sounds.RepairSound", "url here"); }
+//	public String getSpoutSoundLevelUp() { return config.getString("Spout.Sounds.LevelUp", "url here"); }
+}

+ 16 - 11
src/main/java/com/gmail/nossr50/listeners/EntityListener.java

@@ -26,6 +26,7 @@ import org.bukkit.event.entity.FoodLevelChangeEvent;
 import org.bukkit.metadata.FixedMetadataValue;
 
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
@@ -252,6 +253,7 @@ public class EntityListener implements Listener {
      */
     @EventHandler (priority = EventPriority.LOW)
     public void onFoodLevelChange(FoodLevelChangeEvent event) {
+    	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
         if (event.getEntity() instanceof Player) {
             Player player = (Player) event.getEntity();
             
@@ -277,62 +279,65 @@ public class EntityListener implements Listener {
                 int herbLevel = profile.getSkillLevel(SkillType.HERBALISM);
                 int foodChange = newFoodLevel - currentFoodLevel;
                 int rankChange = 0;
+                int FoodRank1 = advancedConfig.getFarmerDietRankChange();
+                int FoodRank2 = advancedConfig.getFarmerDietRankChange() * 2;
+                int FoodRankMax = advancedConfig.getFarmerDietRankChange() * 5;
 
                 switch (food) {
                 case BREAD:
                     /* BREAD RESTORES 2 1/2 HUNGER - RESTORES 5 HUNGER @ 1000 */
-                    rankChange = 200;
+                    rankChange = FoodRank1;
                     break;
 
                 case COOKIE:
                     /* COOKIE RESTORES 1/2 HUNGER - RESTORES 2 HUNGER @ 1000 */
-                    rankChange = 400;
+                    rankChange = FoodRank2;
                     break;
 
                 case MELON:
                     /* MELON RESTORES  1 HUNGER - RESTORES 2 1/2 HUNGER @ 1000 */
-                    rankChange = 400;
+                    rankChange = FoodRank2;
                     break;
 
                 case MUSHROOM_SOUP:
                     /* MUSHROOM SOUP RESTORES 4 HUNGER - RESTORES 6 1/2 HUNGER @ 1000 */
-                    rankChange = 200;
+                    rankChange = FoodRank1;
                     break;
 
                 case CARROT_ITEM:
                     /* CARROT RESTORES 2 HUNGER - RESTORES 4 1/2 HUNGER @ 1000 */
-                    rankChange = 200;
+                    rankChange = FoodRank1;
                     break;
 
                 case POTATO_ITEM:
                     /* POTATO RESTORES 1/2 HUNGER - RESTORES 2 HUNGER @ 1000 */
-                    rankChange = 400;
+                    rankChange = FoodRank2;
                     break;
 
                 case BAKED_POTATO:
                     /* BAKED POTATO RESTORES 3 HUNGER - RESTORES 5 1/2 HUNGER @ 1000 */
-                    rankChange = 200;
+                    rankChange = FoodRank1;
                     break;
 
                 case POISONOUS_POTATO:
                     /* POISONOUS POTATO RESTORES 1 HUNGER - RESTORES 2 1/2 HUNGER @ 1000 */
-                    rankChange = 400;
+                    rankChange = FoodRank2;
                     break;
 
                 case GOLDEN_CARROT:
                     /* GOLDEN CARROT RESTORES 3 HUNGER - RESTORES 5 1/2 HUNGER @ 1000 */
-                    rankChange = 200;
+                    rankChange = FoodRank1;
                     break;
 
                 case PUMPKIN_PIE:
                     /* PUMPKIN PIE RESTORES 4 HUNGER - RESTORES 6 1/2 HUNGER @ 1000 */
-                    rankChange = 200;
+                    rankChange = FoodRank1;
                     break;
                 default:
                     return;
                 }
 
-                for (int i = 200; i <= 1000; i += rankChange) {
+                for (int i = FoodRank1; i <= FoodRankMax; i += rankChange) {
                     if (herbLevel >= i) {
                         foodChange++;
                     }

+ 5 - 1
src/main/java/com/gmail/nossr50/listeners/PlayerListener.java

@@ -25,6 +25,7 @@ import org.bukkit.inventory.ItemStack;
 
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.commands.general.XprateCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.AbilityType;
 import com.gmail.nossr50.datatypes.PlayerProfile;
@@ -46,6 +47,7 @@ import com.gmail.nossr50.util.Skills;
 import com.gmail.nossr50.util.Users;
 
 public class PlayerListener implements Listener {
+    
     private final mcMMO plugin;
 
     public PlayerListener(final mcMMO plugin) {
@@ -91,6 +93,8 @@ public class PlayerListener implements Listener {
      */
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
     public void onPlayerFish(PlayerFishEvent event) {
+    	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+        int shakeUnlockLevel = advancedConfig.getShakeUnlockLevel();
         Player player = event.getPlayer();
         
         if(player.hasMetadata("NPC")) return; // Check if this player is a Citizens NPC
@@ -108,7 +112,7 @@ public class PlayerListener implements Listener {
                     return;
                 }
 
-                if (Users.getProfile(player).getSkillLevel(SkillType.FISHING) >= 150 && Permissions.getInstance().shakeMob(player)) {
+                if (Users.getProfile(player).getSkillLevel(SkillType.FISHING) >= shakeUnlockLevel && Permissions.getInstance().shakeMob(player)) {
                     Fishing.shakeMob(event);
                 }
                 break;

+ 2 - 0
src/main/java/com/gmail/nossr50/mcMMO.java

@@ -51,6 +51,7 @@ import com.gmail.nossr50.commands.skills.UnarmedCommand;
 import com.gmail.nossr50.commands.skills.WoodcuttingCommand;
 import com.gmail.nossr50.commands.spout.MchudCommand;
 import com.gmail.nossr50.commands.spout.XplockCommand;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.config.HiddenConfig;
 import com.gmail.nossr50.config.TreasuresConfig;
@@ -125,6 +126,7 @@ public class mcMMO extends JavaPlugin {
         Config configInstance = Config.getInstance();
         TreasuresConfig.getInstance();
         HiddenConfig.getInstance();
+        AdvancedConfig.getInstance();
 
         List<Repairable> repairables = new ArrayList<Repairable>();
 

+ 8 - 5
src/main/java/com/gmail/nossr50/skills/acrobatics/Acrobatics.java

@@ -2,13 +2,16 @@ package com.gmail.nossr50.skills.acrobatics;
 
 import java.util.Random;
 
+import com.gmail.nossr50.config.AdvancedConfig;
+
 public class Acrobatics {
-    public static final int DODGE_MAX_BONUS_LEVEL = 800;
-    public static final int DODGE_XP_MODIFIER = 120;
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+    public static final int DODGE_MAX_BONUS_LEVEL = advancedConfig.getDodgeMaxBonusLevel();
+    public static final int DODGE_XP_MODIFIER = advancedConfig.getDodgeXPModifier();
 
-    public static final int FALL_XP_MODIFIER = 120;
-    public static final int ROLL_MAX_BONUS_LEVEL = 1000;
-    public static final int ROLL_XP_MODIFIER = 80;
+    public static final int FALL_XP_MODIFIER = advancedConfig.getFallXPModifier();
+    public static final int ROLL_MAX_BONUS_LEVEL = advancedConfig.getRollMaxBonusLevel();
+    public static final int ROLL_XP_MODIFIER = advancedConfig.getRollXPModifier();
 
     private static Random random = new Random();
 

+ 9 - 7
src/main/java/com/gmail/nossr50/skills/archery/Archery.java

@@ -9,20 +9,22 @@ import org.bukkit.Material;
 import org.bukkit.entity.LivingEntity;
 import org.bukkit.inventory.ItemStack;
 
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.util.Misc;
 
 public class Archery {
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
     private static Random random = new Random();
     private static List<TrackedEntity> trackedEntities = new ArrayList<TrackedEntity>();
 
-    public static final int ARROW_TRACKING_MAX_BONUS_LEVEL = 1000;
+    public static final int ARROW_TRACKING_MAX_BONUS_LEVEL = advancedConfig.getRetrieveMaxBonusLevel();
+    
+    public static final int BONUS_DAMAGE_INCREASE_LEVEL = advancedConfig.getSkillShotIncreaseLevel();
+    public static final double BONUS_DAMAGE_INCREASE_PERCENT = advancedConfig.getSkillShotIncreasePercentage();
+    public static final double BONUS_DAMAGE_MAX_BONUS_PERCENTAGE = advancedConfig.getSkillShotBonusMax();
 
-    public static final int BONUS_DAMAGE_INCREASE_LEVEL = 50;
-    public static final double BONUS_DAMAGE_INCREASE_PERCENT = 0.1D;
-    public static final double BONUS_DAMAGE_MAX_BONUS_PERCENTAGE = 2.0D;
-
-    public static final int DAZE_MAX_BONUS_LEVEL = 1000;
-    public static final int DAZE_MODIFIER = 4;
+    public static final int DAZE_MAX_BONUS_LEVEL = advancedConfig.getDazeMaxBonusLevel();
+    public static final int DAZE_MODIFIER = advancedConfig.getDazeModifier();
 
     protected static void incrementTrackerValue(LivingEntity livingEntity) {
         for (TrackedEntity trackedEntity : trackedEntities) {

+ 19 - 11
src/main/java/com/gmail/nossr50/skills/archery/ArcheryManager.java

@@ -4,17 +4,25 @@ import org.bukkit.entity.LivingEntity;
 import org.bukkit.entity.Player;
 import org.bukkit.event.entity.EntityDamageEvent;
 
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class ArcheryManager {
+	AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+	
     private Player player;
     private PlayerProfile profile;
     private int skillLevel;
     private Permissions permissionsInstance;
 
+	private float dazeBonusMax = advancedConfig.getDazeBonusMax();
+	private float dazeMaxBonusLevel = advancedConfig.getDazeMaxBonusLevel();
+	private float retrieveBonusMax = advancedConfig.getRetrieveBonusMax();
+	private float retrieveMaxBonusLevel = advancedConfig.getRetrieveMaxBonusLevel();
+	
     public ArcheryManager (Player player) {
         this.player = player;
         this.profile = Users.getProfile(player);
@@ -45,13 +53,12 @@ public class ArcheryManager {
 
         ArrowTrackingEventHandler eventHandler = new ArrowTrackingEventHandler(this, livingEntity);
 
-        int randomChance = 1000;
-
+        int randomChance = 100;
         if (player.hasPermission("mcmmo.perks.lucky.archery")) {
             randomChance = (int) (randomChance * 0.75);
         }
-
-        if (Archery.getRandom().nextInt(randomChance) < eventHandler.skillModifier) {
+        final float chance = (retrieveBonusMax / retrieveMaxBonusLevel) * skillLevel;
+        if (chance > Archery.getRandom().nextInt(randomChance)) {
             eventHandler.addToTracker();
         }
     }
@@ -74,16 +81,17 @@ public class ArcheryManager {
         }
 
         DazeEventHandler eventHandler = new DazeEventHandler(this, event, defender);
-
-        int randomChance = 2000;
-
+        
+        int randomChance = 100;
+        
         if (player.hasPermission("mcmmo.perks.lucky.archery")) {
             randomChance = (int) (randomChance * 0.75);
         }
-
-        if (Archery.getRandom().nextInt(randomChance) < eventHandler.skillModifier) {
-            eventHandler.handleDazeEffect();
-            eventHandler.sendAbilityMessages();
+        
+        final float chance = (dazeBonusMax / dazeMaxBonusLevel) * skillLevel;
+        if (chance > Archery.getRandom().nextInt(randomChance)) {
+        	eventHandler.handleDazeEffect();
+        	eventHandler.sendAbilityMessages();
         }
     }
 

+ 21 - 12
src/main/java/com/gmail/nossr50/skills/combat/Axes.java

@@ -11,6 +11,7 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.PlayerInventory;
 
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
@@ -20,6 +21,7 @@ import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.Users;
 
 public class Axes {
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
 
     private static Random random = new Random();
 
@@ -33,10 +35,12 @@ public class Axes {
         if(attacker == null)
             return;
 
-        final int MAX_BONUS = 4;
+        final int MAX_BONUS = advancedConfig.getBonusDamageAxesBonusMax();
+        final int MAX_LEVEL = advancedConfig.getBonusDamageAxesMaxBonusLevel();
+        final int INCREASE_LEVEL = MAX_LEVEL / MAX_BONUS;
 
         /* Add 1 DMG for every 50 skill levels */
-        int bonus = Users.getProfile(attacker).getSkillLevel(SkillType.AXES) / 50;
+        int bonus = Users.getProfile(attacker).getSkillLevel(SkillType.AXES) / INCREASE_LEVEL;
 
         if (bonus > MAX_BONUS) {
             bonus = MAX_BONUS;
@@ -73,21 +77,24 @@ public class Axes {
             }
         }
 
-        final int MAX_BONUS_LEVEL = 750;
-        final double PVP_MODIFIER = 1.5;
-        final int PVE_MODIFIER = 2;
+        final int MAX_BONUS_LEVEL = advancedConfig.getAxesCriticalMaxBonusLevel();
+        final double MAX_CHANCE = advancedConfig.getAxesCriticalChance();
+        final double PVP_MODIFIER = advancedConfig.getAxesCriticalPVPModifier();
+        final int PVE_MODIFIER = advancedConfig.getAxesCriticalPVEModifier();
 
         PlayerProfile attackerProfile = Users.getProfile(attacker);
         int skillLevel = attackerProfile.getSkillLevel(SkillType.AXES);
         int skillCheck = Misc.skillCheck(skillLevel, MAX_BONUS_LEVEL);
 
-        int randomChance = 2000;
+        int randomChance = 100;
+        double chance = (MAX_CHANCE / MAX_BONUS_LEVEL) * skillCheck;
 
         if (attacker.hasPermission("mcmmo.perks.lucky.axes")) {
             randomChance = (int) (randomChance * 0.75);
         }
 
-        if (random.nextInt(randomChance) <= skillCheck && !entity.isDead()){
+        if (chance > random.nextInt(randomChance) && !entity.isDead()){
+//        if (random.nextInt(randomChance) <= skillCheck && !entity.isDead()){
             int damage = event.getDamage();
 
             if (entity instanceof Player){
@@ -122,7 +129,8 @@ public class Axes {
             short durabilityDamage = 1; //Start with 1 durability damage
 
             /* Every 30 Skill Levels you gain 1 durability damage */
-            durabilityDamage += Users.getProfile(attacker).getSkillLevel(SkillType.AXES)/50;
+            int impactIncreaseLevel = advancedConfig.getGreaterImpactIncreaseLevel();
+            durabilityDamage += Users.getProfile(attacker).getSkillLevel(SkillType.AXES)/impactIncreaseLevel;
 
             if (!hasArmor(targetPlayer)) {
                 applyGreaterImpact(attacker, target, event);
@@ -150,9 +158,10 @@ public class Axes {
     private static void applyGreaterImpact(Player attacker, LivingEntity target, EntityDamageByEntityEvent event) {
         if(attacker == null)
             return;
-
-        final int GREATER_IMPACT_CHANCE = 25;
-        final double GREATER_IMPACT_MULTIPLIER = 1.5;
+    	
+        final int GREATER_IMPACT_CHANCE = advancedConfig.getGreaterImpactChance();
+        final double GREATER_IMPACT_MULTIPLIER = advancedConfig.getGreaterImpactModifier();
+        final int GREATER_IMPACT_DAMAGE = advancedConfig.getGreaterImpactBonusDamage();
 
         if (!Permissions.getInstance().greaterImpact(attacker)) {
             return;
@@ -165,7 +174,7 @@ public class Axes {
         }
 
         if (random.nextInt(randomChance) <= GREATER_IMPACT_CHANCE) {
-            event.setDamage(event.getDamage() + 2);
+            event.setDamage(event.getDamage() + GREATER_IMPACT_DAMAGE);
             target.setVelocity(attacker.getLocation().getDirection().normalize().multiply(GREATER_IMPACT_MULTIPLIER));
             attacker.sendMessage(LocaleLoader.getString("Axes.Combat.GI.Proc"));
         }

+ 26 - 16
src/main/java/com/gmail/nossr50/skills/gathering/BlastMining.java

@@ -17,6 +17,7 @@ import org.bukkit.event.entity.ExplosionPrimeEvent;
 import org.bukkit.event.player.PlayerInteractEvent;
 
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.AbilityType;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
@@ -27,9 +28,18 @@ import com.gmail.nossr50.util.Skills;
 import com.gmail.nossr50.util.Users;
 
 public class BlastMining {
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
 
     private static Random random = new Random();
-
+    
+	private static int blastMiningRank1 = advancedConfig.getBlastMiningRank1();
+	private static int blastMiningRank2 = advancedConfig.getBlastMiningRank2();
+	private static int blastMiningRank3 = advancedConfig.getBlastMiningRank3();
+	private static int blastMiningRank4 = advancedConfig.getBlastMiningRank4();
+	private static int blastMiningRank5 = advancedConfig.getBlastMiningRank5();
+	private static int blastMiningRank6 = advancedConfig.getBlastMiningRank6();
+	private static int blastMiningRank7 = advancedConfig.getBlastMiningRank7();
+	private static int blastMiningRank8 = advancedConfig.getBlastMiningRank8();
     /**
      * Handler for what blocks drop from the explosion.
      *
@@ -85,14 +95,14 @@ public class BlastMining {
         if(player == null)
             return;
 
-        final int RANK_1_LEVEL = 125;
-        final int RANK_2_LEVEL = 250;
-        final int RANK_3_LEVEL = 375;
-        final int RANK_4_LEVEL = 500;
-        final int RANK_5_LEVEL = 625;
-        final int RANK_6_LEVEL = 750;
-        final int RANK_7_LEVEL = 875;
-        final int RANK_8_LEVEL = 1000;
+        final int RANK_1_LEVEL = blastMiningRank1;
+        final int RANK_2_LEVEL = blastMiningRank2;
+        final int RANK_3_LEVEL = blastMiningRank3;
+        final int RANK_4_LEVEL = blastMiningRank4;
+        final int RANK_5_LEVEL = blastMiningRank5;
+        final int RANK_6_LEVEL = blastMiningRank6;
+        final int RANK_7_LEVEL = blastMiningRank7;
+        final int RANK_8_LEVEL = blastMiningRank8;
 
         int skillLevel = Users.getProfile(player).getSkillLevel(SkillType.MINING);
         float yield = event.getYield();
@@ -178,10 +188,10 @@ public class BlastMining {
         if(player == null)
             return;
 
-        final int RANK_1_LEVEL = 250;
-        final int RANK_2_LEVEL = 500;
-        final int RANK_3_LEVEL = 750;
-        final int RANK_4_LEVEL = 1000;
+        final int RANK_1_LEVEL = blastMiningRank2;
+        final int RANK_2_LEVEL = blastMiningRank4;
+        final int RANK_3_LEVEL = blastMiningRank6;
+        final int RANK_4_LEVEL = blastMiningRank8;
 
         int skillLevel = Users.getProfile(player).getSkillLevel(SkillType.MINING);
         float radius = event.getRadius();
@@ -219,9 +229,9 @@ public class BlastMining {
         if(player == null)
             return;
 
-        final int RANK_1_LEVEL = 500;
-        final int RANK_2_LEVEL = 750;
-        final int RANK_3_LEVEL = 1000;
+        final int RANK_1_LEVEL = blastMiningRank4;
+        final int RANK_2_LEVEL = blastMiningRank6;
+        final int RANK_3_LEVEL = blastMiningRank8;
 
         int skill = Users.getProfile(player).getSkillLevel(SkillType.MINING);
         int damage = event.getDamage();

+ 3 - 1
src/main/java/com/gmail/nossr50/skills/gathering/Fishing.java

@@ -19,6 +19,7 @@ import org.bukkit.material.Wool;
 
 import org.bukkit.craftbukkit.entity.CraftSkeleton;
 
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.config.TreasuresConfig;
 import com.gmail.nossr50.datatypes.PlayerProfile;
@@ -35,6 +36,7 @@ import com.gmail.nossr50.util.Users;
 public class Fishing {
 
     private static Random random = new Random();
+    static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
 
     /**
      * Get the player's current fishing loot tier.
@@ -147,7 +149,7 @@ public class Fishing {
         Item theCatch = (Item) event.getCaught();
 
         if (theCatch.getItemStack().getType() != Material.RAW_FISH) {
-            final int ENCHANTMENT_CHANCE = 10;
+            final int ENCHANTMENT_CHANCE = advancedConfig.getFishingEnchantmentChance();
             boolean enchanted = false;
             ItemStack fishingResults = theCatch.getItemStack();
 

+ 8 - 3
src/main/java/com/gmail/nossr50/skills/gathering/Mining.java

@@ -12,6 +12,7 @@ import org.bukkit.inventory.ItemStack;
 import org.getspout.spoutapi.sound.SoundEffect;
 
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
@@ -26,6 +27,7 @@ import com.gmail.nossr50.util.Users;
 
 public class Mining {
     private static Random random = new Random();
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
 
     /**
      * Handle double drops when using Silk Touch.
@@ -320,17 +322,20 @@ public class Mining {
 
         miningXP(player, block);
 
-        final int MAX_BONUS_LEVEL = 1000;
+        final int MAX_BONUS_LEVEL = advancedConfig.getMiningDoubleDropMaxLevel();
+        int	MAX_CHANCE = advancedConfig.getMiningDoubleDropChance();
+        
         int skillLevel = Users.getProfile(player).getSkillLevel(SkillType.MINING);
         int skillCheck = Misc.skillCheck(skillLevel, MAX_BONUS_LEVEL);
 
-        int randomChance = 1000;
+        int randomChance = 100;
+        int chance = (MAX_CHANCE / MAX_BONUS_LEVEL) * skillLevel;
 
         if (player.hasPermission("mcmmo.perks.lucky.mining")) {
             randomChance = (int) (randomChance * 0.75);
         }
 
-        if (random.nextInt(randomChance) <= skillCheck && Permissions.getInstance().miningDoubleDrops(player)) {
+        if (chance > random.nextInt(randomChance) && Permissions.getInstance().miningDoubleDrops(player)) {
             if (player.getItemInHand().containsEnchantment(Enchantment.SILK_TOUCH)) {
                 silkTouchDrops(block);
             }

+ 8 - 3
src/main/java/com/gmail/nossr50/skills/gathering/WoodCutting.java

@@ -14,6 +14,7 @@ import org.bukkit.material.Tree;
 import org.getspout.spoutapi.sound.SoundEffect;
 
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
@@ -31,6 +32,7 @@ import com.gmail.nossr50.util.Users;
 
 public class WoodCutting {
 
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
     private static Random random = new Random();
 
     /**
@@ -327,7 +329,9 @@ public class WoodCutting {
      * @param block The block being broken
      */
     private static void woodCuttingProcCheck(Player player, Block block) {
-        final int MAX_SKILL_LEVEL = 1000;
+
+    	final int MAX_CHANCE = advancedConfig.getMiningDoubleDropChance();
+        final int MAX_BONUS_LEVEL = advancedConfig.getMiningDoubleDropMaxLevel();
 
         int skillLevel = Users.getProfile(player).getSkillLevel(SkillType.WOODCUTTING);
         byte type = block.getData();
@@ -340,13 +344,14 @@ public class WoodCutting {
 
         Material mat = Material.getMaterial(block.getTypeId());
 
-        int randomChance = 1000;
+        int randomChance = 100;
+        int chance = (MAX_CHANCE / MAX_BONUS_LEVEL) * skillLevel;
 
         if (player.hasPermission("mcmmo.perks.lucky.woodcutting")) {
             randomChance = (int) (randomChance * 0.75);
         }
 
-        if ((skillLevel > MAX_SKILL_LEVEL || random.nextInt(randomChance) <= skillLevel) && Permissions.getInstance().woodcuttingDoubleDrops(player)) {
+        if (chance > random.nextInt(randomChance) && Permissions.getInstance().woodcuttingDoubleDrops(player)) {
             Config configInstance = Config.getInstance();
             ItemStack item;
             Location location;

+ 22 - 11
src/main/java/com/gmail/nossr50/skills/repair/Repair.java

@@ -12,6 +12,7 @@ import org.getspout.spoutapi.SpoutManager;
 import org.getspout.spoutapi.player.SpoutPlayer;
 
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
@@ -27,6 +28,13 @@ public class Repair {
     private static Config configInstance = Config.getInstance();
     private static Permissions permInstance = Permissions.getInstance();
 
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+
+	private static int repairMasteryChanceMax = advancedConfig.getRepairMasteryChanceMax();
+	private static int repairMasteryMaxBonusLevel = advancedConfig.getRepairMasteryMaxLevel();
+	private static int superRepairChanceMax = advancedConfig.getSuperRepairChanceMax();
+	private static int superRepairMaxBonusLevel = advancedConfig.getSuperRepairMaxLevel();
+
     /**
      * Handle the XP gain for repair events.
      *
@@ -198,7 +206,10 @@ public class Repair {
      * @return The final amount of durability repaired to the item
      */
     protected static short repairCalculate(Player player, int skillLevel, short durability, int repairAmount) {
-        float bonus = (float) skillLevel / 500;
+//        float bonus = (float) skillLevel / 500;
+    	float bonus;
+		if(skillLevel >= repairMasteryMaxBonusLevel) bonus = repairMasteryChanceMax;
+		else bonus = (repairMasteryChanceMax / repairMasteryMaxBonusLevel) * skillLevel;
 
         if (permInstance.repairMastery(player)) {
             bonus = (repairAmount * bonus);
@@ -225,21 +236,21 @@ public class Repair {
      * @return true if bonus granted, false otherwise
      */
     public static boolean checkPlayerProcRepair(Player player) {
-        final int MAX_BONUS_LEVEL = 1000;
+    	final int MAX_CHANCE = superRepairChanceMax;
+        final int MAX_BONUS_LEVEL = superRepairMaxBonusLevel;
 
         int skillLevel = Users.getProfile(player).getSkillLevel(SkillType.REPAIR);
 
-        int randomChance = 1000;
+        int randomChance = 100;
+        int chance = (MAX_CHANCE / MAX_BONUS_LEVEL) * skillLevel;
+        if (skillLevel >= MAX_BONUS_LEVEL) chance = MAX_CHANCE;
 
-        if (player.hasPermission("mcmmo.perks.lucky.repair")) {
-            randomChance = (int) (randomChance * 0.75);
+        if (player.hasPermission("mcmmo.perks.lucky.repair")) randomChance = (int) (randomChance * 0.75);
+        
+        if (chance > random.nextInt(randomChance) && permInstance.repairBonus(player)){
+        	player.sendMessage(LocaleLoader.getString("Repair.Skills.FeltEasy"));
+        	return true;
         }
-
-        if ((skillLevel > MAX_BONUS_LEVEL || random.nextInt(randomChance) <= skillLevel) && permInstance.repairBonus(player)) {
-            player.sendMessage(LocaleLoader.getString("Repair.Skills.FeltEasy"));
-            return true;
-        }
-
         return false;
     }
 

+ 11 - 7
src/main/java/com/gmail/nossr50/skills/swords/Swords.java

@@ -2,16 +2,20 @@ package com.gmail.nossr50.skills.swords;
 
 import java.util.Random;
 
+import com.gmail.nossr50.config.AdvancedConfig;
+
 public class Swords {
-    public static final int BLEED_MAX_BONUS_LEVEL = 750;
-    public static final int MAX_BLEED_TICKS = 3;
-    public static final int BASE_BLEED_TICKS = 2;
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+	
+    public static final int BLEED_MAX_BONUS_LEVEL = advancedConfig.getBleedMaxBonusLevel();
+    public static final int MAX_BLEED_TICKS = advancedConfig.getBleedMaxTicks();
+    public static final int BASE_BLEED_TICKS = advancedConfig.getBleedBaseTicks();
 
-    public static final int COUNTER_ATTACK_MAX_BONUS_LEVEL = 600;
-    public static final int COUNTER_ATTACK_MODIFIER = 2;
+    public static final int COUNTER_ATTACK_MAX_BONUS_LEVEL = advancedConfig.getCounterMaxBonusLevel();
+    public static final int COUNTER_ATTACK_MODIFIER = advancedConfig.getCounterModifier();
 
-    public static final int SERRATED_STRIKES_MODIFIER = 4;
-    public static final int SERRATED_STRIKES_BLEED_TICKS = 5;
+    public static final int SERRATED_STRIKES_MODIFIER = advancedConfig.getSerratedStrikesModifier();
+    public static final int SERRATED_STRIKES_BLEED_TICKS = advancedConfig.getSerratedStrikesTicks();
 
     private static Random random = new Random();
 

+ 11 - 5
src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java

@@ -3,6 +3,7 @@ package com.gmail.nossr50.skills.swords;
 import org.bukkit.entity.LivingEntity;
 import org.bukkit.entity.Player;
 
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.util.Combat;
@@ -41,13 +42,16 @@ public class SwordsManager {
         if (Combat.shouldBeAffected(player, defender)) {
             BleedEventHandler eventHandler = new BleedEventHandler(this, defender);
 
-            int randomChance = 1000;
+            int bleedChanceMax = AdvancedConfig.getInstance().getBleedChanceMax();
+            int bleedMaxLevel = AdvancedConfig.getInstance().getBleedMaxBonusLevel();
+            int randomChance = 100;
 
             if (player.hasPermission("mcmmo.perks.lucky.swords")) {
                 randomChance = (int) (randomChance * 0.75);
             }
 
-            if (Swords.getRandom().nextInt(randomChance) < eventHandler.skillModifier) {
+            final float chance = (bleedChanceMax / bleedMaxLevel) * skillLevel;
+            if (chance > Swords.getRandom().nextInt(randomChance)) {
                 eventHandler.addBleedTicks();
                 eventHandler.sendAbilityMessages();
             }
@@ -69,14 +73,16 @@ public class SwordsManager {
 
         if (eventHandler.isHoldingSword()) {
             eventHandler.calculateSkillModifier();
-
-            int randomChance = 2000;
+            int counterChanceMax = AdvancedConfig.getInstance().getCounterChanceMax();
+            int counterMaxLevel = AdvancedConfig.getInstance().getCounterMaxBonusLevel();
+            int randomChance = 100;
 
             if (player.hasPermission("mcmmo.perks.lucky.swords")) {
                 randomChance = (int) (randomChance * 0.75);
             }
 
-            if (Swords.getRandom().nextInt(randomChance) < eventHandler.skillModifier) {
+            final float chance = (counterChanceMax / counterMaxLevel) * skillLevel;
+            if (chance > Swords.getRandom().nextInt(randomChance)) {
                 eventHandler.dealDamage();
                 eventHandler.sendAbilityMessages();
             }

+ 16 - 12
src/main/java/com/gmail/nossr50/skills/taming/Taming.java

@@ -2,24 +2,28 @@ package com.gmail.nossr50.skills.taming;
 
 import java.util.Random;
 
+import com.gmail.nossr50.config.AdvancedConfig;
+
 public class Taming {
-    public static final int ENVIRONMENTALLY_AWARE_ACTIVATION_LEVEL = 100;
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+	
+    public static final int ENVIRONMENTALLY_AWARE_ACTIVATION_LEVEL = advancedConfig.getEnviromentallyAwareUnlock();
 
-    public static final int FAST_FOOD_SERVICE_ACTIVATION_CHANCE = 50;
-    public static final int FAST_FOOD_SERVICE_ACTIVATION_LEVEL = 50;
+    public static final int FAST_FOOD_SERVICE_ACTIVATION_CHANCE = advancedConfig.getFastFoodChance();
+    public static final int FAST_FOOD_SERVICE_ACTIVATION_LEVEL = advancedConfig.getFastFoodUnlock();
 
-    public static final int GORE_BLEED_TICKS = 2;
-    public static final int GORE_MAX_BONUS_LEVEL = 1000;
-    public static final int GORE_MULTIPLIER = 2;
+    public static final int GORE_BLEED_TICKS = advancedConfig.getGoreBleedTicks();
+    public static final int GORE_MAX_BONUS_LEVEL = advancedConfig.getGoreMaxBonusLevel();
+    public static final int GORE_MULTIPLIER = advancedConfig.getGoreModifier();
 
-    public static final int SHARPENED_CLAWS_ACTIVATION_LEVEL = 750;
-    public static final int SHARPENED_CLAWS_BONUS = 2;
+    public static final int SHARPENED_CLAWS_ACTIVATION_LEVEL = advancedConfig.getSharpenedClawsUnlock();
+    public static final int SHARPENED_CLAWS_BONUS = advancedConfig.getSharpenedClawsBonus();
 
-    public static final int SHOCK_PROOF_ACTIVATION_LEVEL = 500;
-    public static final int SHOCK_PROOF_MODIFIER = 6;
+    public static final int SHOCK_PROOF_ACTIVATION_LEVEL = advancedConfig.getShockProofUnlock();
+    public static final int SHOCK_PROOF_MODIFIER = advancedConfig.getShockProofModifier();
 
-    public static final int THICK_FUR_ACTIVATION_LEVEL = 250;
-    public static final int THICK_FUR_MODIFIER = 2;
+    public static final int THICK_FUR_ACTIVATION_LEVEL = advancedConfig.getThickFurUnlock();
+    public static final int THICK_FUR_MODIFIER = advancedConfig.getThickFurModifier();
 
     private static Random random = new Random();
 

+ 7 - 3
src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java

@@ -8,6 +8,7 @@ import org.bukkit.event.entity.EntityDamageEvent;
 import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
 import org.bukkit.inventory.ItemStack;
 
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
@@ -101,14 +102,17 @@ public class TamingManager {
         }
 
         GoreEventHandler eventHandler = new GoreEventHandler(this, event);
-
-        int randomChance = 1000;
+        
+        int goreChanceMax = AdvancedConfig.getInstance().getGoreChanceMax();
+        int goreMaxLevel = AdvancedConfig.getInstance().getGoreMaxBonusLevel();
+        int randomChance = 100;
 
         if (player.hasPermission("mcmmo.perks.lucky.taming")) {
             randomChance = (int) (randomChance * 0.75);
         }
 
-        if (Taming.getRandom().nextInt(randomChance) < eventHandler.skillModifier) {
+        final float chance = (goreChanceMax / goreMaxLevel) * skillLevel;
+        if (chance > Taming.getRandom().nextInt(randomChance)) {
             eventHandler.modifyEventDamage();
             eventHandler.applyBleed();
             eventHandler.sendAbilityMessage();

+ 13 - 6
src/main/java/com/gmail/nossr50/skills/unarmed/Unarmed.java

@@ -2,16 +2,23 @@ package com.gmail.nossr50.skills.unarmed;
 
 import java.util.Random;
 
+import com.gmail.nossr50.config.AdvancedConfig;
+
 public class Unarmed {
-    public static final int BONUS_DAMAGE_MAX_BONUS_MODIFIER = 8;
-    public static final int BONUS_DAMAGE_INCREASE_LEVEL = 50;
-    public static final int DEFLECT_MAX_BONUS_LEVEL = 1000;
-    public static final int DISARM_MAX_BONUS_LEVEL = 1000;
-    public static final int IRON_GRIP_MAX_BONUS_LEVEL = 1000;
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+	
+    public static final int BONUS_DAMAGE_MAX_BONUS_MODIFIER = advancedConfig.getIronArmBonus();
+    public static final int BONUS_DAMAGE_INCREASE_LEVEL = advancedConfig.getIronArmIncreaseLevel();
+    public static final int DEFLECT_MAX_CHANCE = advancedConfig.getDisarmChanceMax() ;
+    public static final int DEFLECT_MAX_BONUS_LEVEL = advancedConfig.getDisarmMaxBonusLevel();
+    public static final int DISARM_MAX_CHANCE = advancedConfig.getDeflectChanceMax();
+    public static final int DISARM_MAX_BONUS_LEVEL = advancedConfig.getDeflectMaxBonusLevel();
+    public static final int IRON_GRIP_MAX_CHANCE = advancedConfig.getIronGripChanceMax();
+    public static final int IRON_GRIP_MAX_BONUS_LEVEL = advancedConfig.getIronGripMaxBonusLevel();
 
     private static Random random = new Random();
 
     protected static Random getRandom() {
         return random;
     }
-}
+}

+ 19 - 9
src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java

@@ -3,6 +3,7 @@ package com.gmail.nossr50.skills.unarmed;
 import org.bukkit.entity.Player;
 import org.bukkit.event.entity.EntityDamageEvent;
 
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
 import com.gmail.nossr50.util.Permissions;
@@ -42,13 +43,16 @@ public class UnarmedManager {
         if (eventHandler.isHoldingItem()) {
             eventHandler.calculateSkillModifier();
 
-            int randomChance = 3000;
+            int disarmChanceMax = AdvancedConfig.getInstance().getDisarmChanceMax();
+            int disarmMaxLevel = AdvancedConfig.getInstance().getDisarmMaxBonusLevel();
+            int randomChance = 100;
 
             if (player.hasPermission("mcmmo.perks.lucky.unarmed")) {
                 randomChance = (int) (randomChance * 0.75);
             }
 
-            if (Unarmed.getRandom().nextInt(randomChance) < eventHandler.skillModifier) {
+            final float chance = (disarmChanceMax / disarmMaxLevel) * skillLevel;
+            if (chance > Unarmed.getRandom().nextInt(randomChance)) {
                 if (!hasIronGrip(defender)) {
                     eventHandler.sendAbilityMessage();
                     eventHandler.handleDisarm();
@@ -76,13 +80,16 @@ public class UnarmedManager {
 
         DeflectEventHandler eventHandler = new DeflectEventHandler(this, event);
 
-        int randomChance = 2000;
-
+        int deflectChanceMax = AdvancedConfig.getInstance().getDeflectChanceMax();
+        int deflectMaxLevel = AdvancedConfig.getInstance().getDeflectMaxBonusLevel();
+        int randomChance = 100;
+        
         if (player.hasPermission("mcmmo.perks.lucky.unarmed")) {
             randomChance = (int) (randomChance * 0.75);
         }
-
-        if (Unarmed.getRandom().nextInt(randomChance) < eventHandler.skillModifier) {
+        
+        final float chance = (deflectChanceMax / deflectMaxLevel) * skillLevel;
+        if (chance > Unarmed.getRandom().nextInt(randomChance)) {
             eventHandler.cancelEvent();
             eventHandler.sendAbilityMessage();
         }
@@ -129,13 +136,16 @@ public class UnarmedManager {
 
         IronGripEventHandler eventHandler = new IronGripEventHandler(this, defender);
 
-        int randomChance = 1000;
+        int ironGripChanceMax = AdvancedConfig.getInstance().getIronGripChanceMax();
+        int ironGripMaxLevel = AdvancedConfig.getInstance().getIronGripMaxBonusLevel();
+        int randomChance = 100;
 
         if (defender.hasPermission("mcmmo.perks.lucky.unarmed")) {
             randomChance = (int) (randomChance * 0.75);
         }
-
-        if (Unarmed.getRandom().nextInt(randomChance) < eventHandler.skillModifier) {
+        
+        final float chance = (ironGripChanceMax / ironGripMaxLevel) * skillLevel;
+        if (chance > Unarmed.getRandom().nextInt(randomChance)) {
             eventHandler.sendAbilityMessages();
             return true;
         }

+ 6 - 4
src/main/java/com/gmail/nossr50/spout/SpoutStuff.java

@@ -20,6 +20,7 @@ import org.getspout.spoutapi.keyboard.Keyboard;
 import org.getspout.spoutapi.player.SpoutPlayer;
 
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.SpoutConfig;
 import com.gmail.nossr50.datatypes.PlayerProfile;
 import com.gmail.nossr50.datatypes.SkillType;
@@ -29,6 +30,7 @@ import com.gmail.nossr50.util.Users;
 
 public class SpoutStuff {
     private static mcMMO plugin = mcMMO.p;
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
 
     public final static String spoutDirectory = mcMMO.getMainDirectory() + "Resources" + File.separator;
     public final static String hudDirectory = spoutDirectory + "HUD" + File.separator;
@@ -548,16 +550,16 @@ public class SpoutStuff {
      * @return the notification tier of the skill
      */
     private static Integer getNotificationTier(Integer level) {
-        if (level >= 800) {
+        if (level >= advancedConfig.getSpoutNotificationTier4()) {
             return 5;
         }
-        else if (level >= 600) {
+        else if (level >= advancedConfig.getSpoutNotificationTier3()) {
             return 4;
         }
-        else if (level >= 400) {
+        else if (level >= advancedConfig.getSpoutNotificationTier2()) {
             return 3;
         }
-        else if (level >= 200) {
+        else if (level >= advancedConfig.getSpoutNotificationTier1()) {
             return 2;
         }
         else {

+ 4 - 1
src/main/java/com/gmail/nossr50/util/Skills.java

@@ -11,6 +11,7 @@ import org.getspout.spoutapi.SpoutManager;
 import org.getspout.spoutapi.player.SpoutPlayer;
 
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.config.SpoutConfig;
 import com.gmail.nossr50.datatypes.AbilityType;
@@ -24,6 +25,8 @@ import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.spout.SpoutStuff;
 
 public class Skills {
+	static AdvancedConfig advancedConfig = AdvancedConfig.getInstance();
+	public static int abilityLengthIncreaseLevel = advancedConfig.getAbilityLength();
 
     private final static int TIME_CONVERSION_FACTOR = 1000;
     private final static double MAX_DISTANCE_AWAY = 10.0;
@@ -422,7 +425,7 @@ public class Skills {
             }
         }
 
-        int ticks = 2 + (profile.getSkillLevel(type) / 50);
+        int ticks = 2 + (profile.getSkillLevel(type) / abilityLengthIncreaseLevel);
 
         if (player.hasPermission("mcmmo.perks.activationtime.twelveseconds")) {
             ticks = ticks + 12;

+ 116 - 0
src/main/resources/advanced.yml

@@ -0,0 +1,116 @@
+#
+#  Advanced configuration
+#  
+#  For advanced users only! There is no need to change anything here. 
+#
+#  You can customize almost every aspect of every skill here.  
+#  Its mainly here if you've changed "Experience.Formula.Curve_Modifier"
+#  Configure at what level you get better with certain abilities.
+#
+#####
+
+#
+#  Settings for the Skills
+###
+Skills:
+    General:
+        Ability_IncreaseLevel: 50
+    Acrobatics:
+        Dodge_ChanceMax: 20
+        Dodge_MaxBonusLevel: 800
+        Roll_ChanceMax: 100
+        Roll_MaxBonusLevel: 1000
+        GracefulRoll_ChanceMax: 100
+        GracefulRoll_MaxBonusLevel: 500
+        Dodge_XP_Modifier: 120
+        Roll_XP_Modifier: 80
+        Fall_XP_Modifier: 120
+    Archery:
+        SkillShot_IncreaseLevel: 50
+        SkillShot_IncreasePercentage: 0.1D
+        SkillShot_MaxBonus: 2.0D
+        Daze_MaxChance: 50
+        Daze_MaxBonusLevel: 1000
+        Daze_Modifier: 4
+        Retrieve_MaxBonus: 100
+        Retrieve_MaxBonusLevel: 1000
+    Axes:
+        DamageIncrease_MaxBonus: 4
+        DamageIncrease_MaxBonusLevel: 200
+        AxesCritical_MaxChance: 37.50
+        AxesCritical_MaxBonusLevel: 750
+        AxesCritical_PVP_Modifier: 1.5
+        AxesCritical_PVE_Modifier: 2
+        GreaterImpact_Chance: 25
+        GreaterImpact_IncreaseLevel: 50
+        GreaterImpact_KnockbackModifier: 1.5
+        GreaterImpact_BonusDamage: 2
+    Fishing:
+        Shake_UnlockLevel: 150
+        Enchantment_Chance: 10
+    Herbalism:
+        Food_RankChange: 200
+        GreenThumb_StageChange: 200
+        GreenThumb_ChanceMax: 100
+        GreenThumb_MaxBonusLevel: 1500
+        DoubleDrops_ChanceMax: 100
+        DoubleDrops_MaxBonusLevel: 1000
+    Mining:
+        DoubleDrops_ChanceMax: 100
+        DoubleDrops_MaxBonusLevel: 1000
+        BlastMining_Rank1: 125
+        BlastMining_Rank2: 250
+        BlastMining_Rank3: 375
+        BlastMining_Rank4: 500
+        BlastMining_Rank5: 625
+        BlastMining_Rank6: 750
+        BlastMining_Rank7: 875
+        BlastMining_Rank8: 1000
+    Repair:
+        RepairMastery_ChanceMax: 200
+        RepairMastery_MaxBonusLevel: 1000
+        SuperRepair_ChanceMax: 100
+        SuperRepair_MaxBonusLevel: 1000
+    Swords:
+        Bleed_ChanceMax: 75
+        Bleed_MaxBonusLevel: 750
+        Bleed_MaxTicks: 3
+        Bleed_BaseTicks: 2
+        CounterAttack_ChanceMax: 30
+        CounterAttack_MaxBonusLevel: 600
+        Counter_DamageModifier: 2
+        SerratedStrikes_DamageModifier: 4
+        SerratedStrikes_BleedTicks: 5
+    Taming:
+        Gore_ChanceMax: 100
+        Gore_MaxBonusLevel: 1000
+        Gore_BleedTicks: 2
+        Gore_Modifier: 2
+        FastFood_UnlockLevel: 50
+        FastFood_Chance: 50
+        EnvironmentallyAware_UnlockLevel: 100
+        ThickFur_UnlockLevel: 250
+        ThickFur_Modifier: 2
+        ShockProof_UnlockLevel: 500
+        ShockProof_Modifier: 6
+        SharpenedClaws_UnlockLevel: 750
+        SharpenedClaws_Bonus: 2
+    Unarmed:
+        Disarm_ChanceMax: 33
+        Disarm_MaxBonusLevel: 1000
+        Deflect_ChanceMax: 50
+        Deflect_MaxBonusLevel: 1000
+        IronGrip_ChanceMax: 100
+        IronGrip_MaxBonusLevel: 1000
+        IronArmBonus: 8
+        IronArm_IncreaseLevel: 50
+    Woodcutting:
+        LeafBlower_UnlockLevel: 100
+        DoubleDrops_ChanceMax: 100
+        DoubleDrops_MaxBonusLevel: 1000
+Spout:
+    Notifications:
+        Tier1: 200
+        Tier2: 400
+        Tier3: 600
+        Tier4: 800

+ 28 - 28
src/main/resources/locale/locale_en_US.properties

@@ -18,7 +18,7 @@
 # ACROBATICS
 Acrobatics.Ability.Proc=[[GREEN]]**Graceful Landing**
 Acrobatics.Combat.Proc=[[GREEN]]**Dodged**
-Acrobatics.DodgeChance=[[RED]]Dodge Chance: [[YELLOW]]{0}
+Acrobatics.DodgeChance=[[RED]]Dodge Chance: [[YELLOW]]{0}%
 Acrobatics.Effect.0=Roll
 Acrobatics.Effect.1=Reduces or Negates fall damage
 Acrobatics.Effect.2=Graceful Roll
@@ -26,15 +26,15 @@ Acrobatics.Effect.3=Twice as effective as a normal Roll
 Acrobatics.Effect.4=Dodge
 Acrobatics.Effect.5=Reduce attack damage by half
 Acrobatics.Listener=Acrobatics: 
-Acrobatics.Roll.Chance=[[RED]]Roll Chance: [[YELLOW]]{0}
-Acrobatics.Roll.GraceChance=[[RED]]Graceful Roll Chance: [[YELLOW]]{0}
+Acrobatics.Roll.Chance=[[RED]]Roll Chance: [[YELLOW]]{0}%
+Acrobatics.Roll.GraceChance=[[RED]]Graceful Roll Chance: [[YELLOW]]{0}%
 Acrobatics.Roll.Text=**Rolled**
 Acrobatics.SkillName=ACROBATICS
 Acrobatics.Skillup=[[YELLOW]]Acrobatics skill increased by {0}. Total ({1})
 
 #ARCHERY
-Archery.Combat.DazeChance=[[RED]]Chance to Daze: [[YELLOW]]{0}
-Archery.Combat.RetrieveChance=[[RED]]Chance to Retrieve Arrows: [[YELLOW]]{0}
+Archery.Combat.DazeChance=[[RED]]Chance to Daze: [[YELLOW]]{0}%
+Archery.Combat.RetrieveChance=[[RED]]Chance to Retrieve Arrows: [[YELLOW]]{0}%
 Archery.Combat.SkillshotBonus=[[RED]]Skill Shot Bonus Damage: [[YELLOW]]{0}
 Archery.Effect.0=Skill Shot
 Archery.Effect.1=Increases damage done with bows
@@ -100,7 +100,7 @@ Excavation.Skillup=[[YELLOW]]Excavation skill increased by {0}. Total ({1})
 
 #FISHING
 Fishing.Ability.Info=[[RED]]Magic Hunter: [[GRAY]] **Improves With Treasure Hunter Rank**
-Fishing.Ability.Locked.0=LOCKED UNTIL 150+ SKILL (SHAKE)
+Fishing.Ability.Locked.0=LOCKED UNTIL {0}+ SKILL (SHAKE)
 Fishing.Ability.Rank=[[RED]]Treasure Hunter Rank: [[YELLOW]]{0}/5
 Fishing.Ability.Shake=[[RED]]Shake Chance: [[YELLOW]]{0}%
 Fishing.Effect.0=Treasure Hunter (Passive)
@@ -109,7 +109,7 @@ Fishing.Effect.2=Magic Hunter
 Fishing.Effect.3=Find Enchanted Items
 Fishing.Effect.4=Shake (vs. Entities)
 Fishing.Effect.5=Shake items off of mobs w/ fishing pole
-Fishing.Enchant.Chance=[[RED]]Magic Hunter Chance: [[YELLOW]]{0}
+Fishing.Enchant.Chance=[[RED]]Magic Hunter Chance: [[YELLOW]]{0}%
 Fishing.ItemFound=[[GRAY]]Treasure found!
 Fishing.Listener=Fishing: 
 Fishing.MagicFound=[[GRAY]]You feel a touch of magic with this catch...
@@ -117,10 +117,10 @@ Fishing.SkillName=FISHING
 Fishing.Skillup=[[YELLOW]]Fishing skill increased by {0}. Total ({1})
 
 #HERBALISM
-Herbalism.Ability.DoubleDropChance=[[RED]]Double Drop Chance: [[YELLOW]]{0}
+Herbalism.Ability.DoubleDropChance=[[RED]]Double Drop Chance: [[YELLOW]]{0}%
 Herbalism.Ability.FD=[[RED]]Farmers Diet: [[YELLOW]]Rank {0}
 Herbalism.Ability.GTe.Length=[[RED]]Green Terra Length: [[YELLOW]]{0}s
-Herbalism.Ability.GTh.Chance=[[RED]]Green Thumb Chance: [[YELLOW]]{0}
+Herbalism.Ability.GTh.Chance=[[RED]]Green Thumb Chance: [[YELLOW]]{0}%
 Herbalism.Ability.GTh.Fail=[[RED]]**GREEN THUMB FAIL**
 Herbalism.Ability.GTh.Stage=[[RED]]Green Thumb Stage: [[YELLOW]] Wheat grows in stage {0}
 Herbalism.Ability.GTh=[[GREEN]]**GREEN THUMB**
@@ -147,9 +147,9 @@ Herbalism.Skillup=[[YELLOW]]Herbalism skill increased by {0}. Total ({1})
 
 #MINING
 Mining.Ability.Length=[[RED]]Super Breaker Length: [[YELLOW]]{0}s
-Mining.Ability.Locked.0=LOCKED UNTIL 125+ SKILL (BLAST MINING)
-Mining.Ability.Locked.1=LOCKED UNTIL 250+ SKILL (BIGGER BOMBS)
-Mining.Ability.Locked.2=LOCKED UNTIL 500+ SKILL (DEMOLITIONS EXPERTISE)
+Mining.Ability.Locked.0=LOCKED UNTIL {0}+ SKILL (BLAST MINING)
+Mining.Ability.Locked.1=LOCKED UNTIL {0}+ SKILL (BIGGER BOMBS)
+Mining.Ability.Locked.2=LOCKED UNTIL {0}+ SKILL (DEMOLITIONS EXPERTISE)
 Mining.Ability.Lower=[[GRAY]]**YOU LOWER YOUR PICKAXE**
 Mining.Ability.Ready=[[GREEN]]**YOU READY YOUR PICKAXE**
 Mining.Effect.0=Super Breaker (ABILITY)
@@ -163,7 +163,7 @@ Mining.Effect.7=Increases TNT explosion radius
 Mining.Effect.8=Demolitions Expertise
 Mining.Effect.9=Decreases damage from TNT explosions
 Mining.Effect.Decrease=[[RED]]Demolitions Expert Damage Decrease: [[YELLOW]]{0}
-Mining.Effect.DropChance=[[RED]]Double Drop Chance: [[YELLOW]]{0}
+Mining.Effect.DropChance=[[RED]]Double Drop Chance: [[YELLOW]]{0}%
 Mining.Listener=Mining: 
 Mining.SkillName=MINING
 Mining.Skills.SuperBreaker.Off=[[RED]]**Super Breaker has worn off**
@@ -221,9 +221,9 @@ Repair.Skills.FeltEasy=[[GRAY]]That felt easy.
 Repair.Skills.FullDurability=[[GRAY]]That is at full durability.
 Repair.Skills.SalvageSuccess=[[GRAY]]Item salvaged!
 Repair.Skills.NotFullDurability=[[DARK_RED]]You can't salvage damaged items.
-Repair.Skills.Mastery=[[RED]]Repair Mastery: [[YELLOW]]Extra {0} durability restored
+Repair.Skills.Mastery=[[RED]]Repair Mastery: [[YELLOW]]Extra {0}% durability restored
 Repair.Skills.StackedItems=[[DARK_RED]]You can't repair stacked items.
-Repair.Skills.Super.Chance=[[RED]]Super Repair Chance: [[YELLOW]]{0}
+Repair.Skills.Super.Chance=[[RED]]Super Repair Chance: [[YELLOW]]{0}%
 Repair.Skillup=[[YELLOW]]Repair skill increased by {0}. Total ({1})
 
 ##Arcane Forging
@@ -238,13 +238,13 @@ Repair.Arcane.Rank=[[RED]]Arcane Forging: [[YELLOW]]Rank {0}/4
 #SWORDS
 Swords.Ability.Lower=[[GRAY]]**YOU LOWER YOUR SWORD**
 Swords.Ability.Ready=[[GREEN]]**YOU READY YOUR SWORD**
-Swords.Combat.Bleed.Chance=[[RED]]Bleed Chance: [[YELLOW]]{0}
+Swords.Combat.Bleed.Chance=[[RED]]Bleed Chance: [[YELLOW]]{0}%
 Swords.Combat.Bleed.Length=[[RED]]Bleed Length: [[YELLOW]]{0} ticks
 Swords.Combat.Bleed.Note=[[GRAY]]NOTE: [[YELLOW]]1 Tick happens every 2 seconds
 Swords.Combat.Bleeding.Started=[[DARK_RED]] You're bleeding!
 Swords.Combat.Bleeding.Stopped=[[GRAY]]The bleeding has [[GREEN]]stopped[[GRAY]]!
 Swords.Combat.Bleeding=[[GREEN]]**ENEMY BLEEDING**
-Swords.Combat.Counter.Chance=[[RED]]Counter Attack Chance: [[YELLOW]]{0}
+Swords.Combat.Counter.Chance=[[RED]]Counter Attack Chance: [[YELLOW]]{0}%
 Swords.Combat.Counter.Hit=[[DARK_RED]]Hit with a counter-attack!
 Swords.Combat.Countered=[[GREEN]]**COUNTER-ATTACKED**
 Swords.Combat.SS.Struck=[[DARK_RED]]Struck by SERRATED STRIKES!
@@ -276,13 +276,13 @@ Taming.Ability.Bonus.5=Explosives do 1/6 normal damage
 Taming.Ability.Bonus.6=Sharpened Claws
 Taming.Ability.Bonus.7=+2 Damage
 Taming.Ability.Bonus.8=Fast Food Service
-Taming.Ability.Bonus.9=50% Chance for heal on attack
-Taming.Ability.Locked.0=LOCKED UNTIL 100+ SKILL (ENVIRONMENTALLY AWARE)
-Taming.Ability.Locked.1=LOCKED UNTIL 250+ SKILL (THICK FUR)
-Taming.Ability.Locked.2=LOCKED UNTIL 500+ SKILL (SHOCK PROOF)
-Taming.Ability.Locked.3=LOCKED UNTIL 750+ SKILL (SHARPENED CLAWS)
-Taming.Ability.Locked.4=LOCKED UNTIL 50+ SKILL (FAST FOOD SERVICE)
-Taming.Combat.Chance.Gore=[[RED]]Gore Chance: [[YELLOW]]{0}
+Taming.Ability.Bonus.9={0}% Chance for heal on attack
+Taming.Ability.Locked.0=LOCKED UNTIL {0}+ SKILL (ENVIRONMENTALLY AWARE)
+Taming.Ability.Locked.1=LOCKED UNTIL {0}+ SKILL (THICK FUR)
+Taming.Ability.Locked.2=LOCKED UNTIL {0}+ SKILL (SHOCK PROOF)
+Taming.Ability.Locked.3=LOCKED UNTIL {0}+ SKILL (SHARPENED CLAWS)
+Taming.Ability.Locked.4=LOCKED UNTIL {0}+ SKILL (FAST FOOD SERVICE)
+Taming.Combat.Chance.Gore=[[RED]]Gore Chance: [[YELLOW]]{0}%
 Taming.Effect.0=Beast Lore
 Taming.Effect.1=Bone-whacking inspects wolves & ocelots
 Taming.Effect.10=Shock Proof
@@ -313,8 +313,8 @@ Taming.Summon.Fail.Wolf=[[RED]]You have too many wolves nearby to summon any mor
 Unarmed.Ability.Berserk.Length=[[RED]]Berserk Length: [[YELLOW]]{0}s
 Unarmed.Ability.Bonus.0=Iron Arm Style
 Unarmed.Ability.Bonus.1=+{0} DMG Upgrade
-Unarmed.Ability.Chance.ArrowDeflect=[[RED]]Arrow Deflect Chance: [[YELLOW]]{0}
-Unarmed.Ability.Chance.Disarm=[[RED]]Disarm Chance: [[YELLOW]]{0}
+Unarmed.Ability.Chance.ArrowDeflect=[[RED]]Arrow Deflect Chance: [[YELLOW]]{0}%
+Unarmed.Ability.Chance.Disarm=[[RED]]Disarm Chance: [[YELLOW]]{0}%
 Unarmed.Ability.Lower=[[GRAY]]**YOU LOWER YOUR FISTS**
 Unarmed.Ability.Ready=[[GREEN]]**YOU READY YOUR FISTS**
 Unarmed.Effect.0=Berserk (ABILITY)
@@ -337,9 +337,9 @@ Unarmed.Skillup=[[YELLOW]]Unarmed skill increased by {0}. Total ({1})
 #WOODCUTTING
 Woodcutting.Ability.0=Leaf Blower
 Woodcutting.Ability.1=Blow away leaves
-Woodcutting.Ability.Chance.DDrop=[[RED]]Double Drop Chance: [[YELLOW]]{0}
+Woodcutting.Ability.Chance.DDrop=[[RED]]Double Drop Chance: [[YELLOW]]{0}%
 Woodcutting.Ability.Length=[[RED]]Tree Feller Length: [[YELLOW]]{0}s
-Woodcutting.Ability.Locked.0=LOCKED UNTIL 100+ SKILL (LEAF BLOWER)
+Woodcutting.Ability.Locked.0=LOCKED UNTIL {0}+ SKILL (LEAF BLOWER)
 Woodcutting.Effect.0=Tree Feller (ABILITY)
 Woodcutting.Effect.1=Make trees explode
 Woodcutting.Effect.2=Leaf Blower