Explorar o código

SkillUtils cleanup, EventUtils creation

Move some functions in SkillUtils to more relevant locations.

Begin work on utility class to handle all event calls.
GJ %!s(int64=11) %!d(string=hai) anos
pai
achega
468fbdab56
Modificáronse 32 ficheiros con 408 adicións e 503 borrados
  1. 1 1
      src/main/java/com/gmail/nossr50/api/ExperienceAPI.java
  2. 1 2
      src/main/java/com/gmail/nossr50/commands/experience/AddlevelsCommand.java
  3. 1 2
      src/main/java/com/gmail/nossr50/commands/experience/AddxpCommand.java
  4. 1 2
      src/main/java/com/gmail/nossr50/commands/experience/ExperienceCommand.java
  5. 1 2
      src/main/java/com/gmail/nossr50/commands/experience/MmoeditCommand.java
  6. 1 2
      src/main/java/com/gmail/nossr50/commands/experience/SkillresetCommand.java
  7. 1 1
      src/main/java/com/gmail/nossr50/commands/hardcore/HardcoreCommand.java
  8. 1 1
      src/main/java/com/gmail/nossr50/commands/hardcore/VampirismCommand.java
  9. 10 12
      src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java
  10. 2 3
      src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java
  11. 1 2
      src/main/java/com/gmail/nossr50/commands/skills/SkillGuideCommand.java
  12. 1 1
      src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java
  13. 1 1
      src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java
  14. 147 2
      src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java
  15. 2 6
      src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java
  16. 21 0
      src/main/java/com/gmail/nossr50/datatypes/skills/AbilityType.java
  17. 28 25
      src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java
  18. 9 9
      src/main/java/com/gmail/nossr50/listeners/BlockListener.java
  19. 18 17
      src/main/java/com/gmail/nossr50/listeners/PlayerListener.java
  20. 2 3
      src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java
  21. 1 1
      src/main/java/com/gmail/nossr50/runnables/database/FormulaConversionTask.java
  22. 1 1
      src/main/java/com/gmail/nossr50/skills/child/ChildConfig.java
  23. 2 1
      src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java
  24. 2 1
      src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java
  25. 62 0
      src/main/java/com/gmail/nossr50/util/EventUtils.java
  26. 4 4
      src/main/java/com/gmail/nossr50/util/HardcoreManager.java
  27. 1 2
      src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java
  28. 27 32
      src/main/java/com/gmail/nossr50/util/commands/CommandUtils.java
  29. 13 14
      src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java
  30. 3 3
      src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java
  31. 41 350
      src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java
  32. 1 0
      src/main/resources/locale/locale_en_US.properties

+ 1 - 1
src/main/java/com/gmail/nossr50/api/ExperienceAPI.java

@@ -414,7 +414,7 @@ public final class ExperienceAPI {
         int powerLevel = 0;
         PlayerProfile profile = getOfflineProfile(playerName);
 
-        for (SkillType type : SkillType.nonChildSkills()) {
+        for (SkillType type : SkillType.NON_CHILD_SKILLS) {
             powerLevel += profile.getSkillLevel(type);
         }
 

+ 1 - 2
src/main/java/com/gmail/nossr50/commands/experience/AddlevelsCommand.java

@@ -7,7 +7,6 @@ import com.gmail.nossr50.datatypes.skills.SkillType;
 import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.skills.SkillUtils;
 
 public class AddlevelsCommand extends ExperienceCommand {
     @Override
@@ -36,6 +35,6 @@ public class AddlevelsCommand extends ExperienceCommand {
 
     @Override
     protected void handlePlayerMessageSkill() {
-        player.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.1", value, SkillUtils.getSkillName(skill)));
+        player.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.1", value, skill.getSkillName()));
     }
 }

+ 1 - 2
src/main/java/com/gmail/nossr50/commands/experience/AddxpCommand.java

@@ -5,7 +5,6 @@ import org.bukkit.command.CommandSender;
 import com.gmail.nossr50.datatypes.skills.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.skills.SkillUtils;
 
 public class AddxpCommand extends ExperienceCommand {
     @Override
@@ -35,6 +34,6 @@ public class AddxpCommand extends ExperienceCommand {
 
     @Override
     protected void handlePlayerMessageSkill() {
-        player.sendMessage(LocaleLoader.getString("Commands.addxp.AwardSkill", value, SkillUtils.getSkillName(skill)));
+        player.sendMessage(LocaleLoader.getString("Commands.addxp.AwardSkill", value, skill.getSkillName()));
     }
 }

+ 1 - 2
src/main/java/com/gmail/nossr50/commands/experience/ExperienceCommand.java

@@ -18,7 +18,6 @@ import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.commands.CommandUtils;
 import com.gmail.nossr50.util.player.UserManager;
-import com.gmail.nossr50.util.skills.SkillUtils;
 
 import com.google.common.collect.ImmutableList;
 
@@ -149,7 +148,7 @@ public abstract class ExperienceCommand implements TabExecutor {
             sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardAll.2", playerName));
         }
         else {
-            sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", SkillUtils.getSkillName(skill), playerName));
+            sender.sendMessage(LocaleLoader.getString("Commands.addlevels.AwardSkill.2", skill.getSkillName(), playerName));
         }
     }
 

+ 1 - 2
src/main/java/com/gmail/nossr50/commands/experience/MmoeditCommand.java

@@ -8,7 +8,6 @@ import com.gmail.nossr50.events.experience.McMMOPlayerLevelDownEvent;
 import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.skills.SkillUtils;
 
 public class MmoeditCommand extends ExperienceCommand {
     @Override
@@ -46,6 +45,6 @@ public class MmoeditCommand extends ExperienceCommand {
 
     @Override
     protected void handlePlayerMessageSkill() {
-        player.sendMessage(LocaleLoader.getString("Commands.mmoedit.Modified.1", SkillUtils.getSkillName(skill), value));
+        player.sendMessage(LocaleLoader.getString("Commands.mmoedit.Modified.1", skill.getSkillName(), value));
     }
 }

+ 1 - 2
src/main/java/com/gmail/nossr50/commands/experience/SkillresetCommand.java

@@ -12,7 +12,6 @@ import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.commands.CommandUtils;
 import com.gmail.nossr50.util.player.UserManager;
-import com.gmail.nossr50.util.skills.SkillUtils;
 
 public class SkillresetCommand extends ExperienceCommand {
     private CommandSender sender;
@@ -117,6 +116,6 @@ public class SkillresetCommand extends ExperienceCommand {
 
     @Override
     protected void handlePlayerMessageSkill() {
-        player.sendMessage(LocaleLoader.getString("Commands.Reset.Single", SkillUtils.getSkillName(skill)));
+        player.sendMessage(LocaleLoader.getString("Commands.Reset.Single", skill.getSkillName()));
     }
 }

+ 1 - 1
src/main/java/com/gmail/nossr50/commands/hardcore/HardcoreCommand.java

@@ -50,7 +50,7 @@ public class HardcoreCommand extends HardcoreModeCommand {
 
     private void toggle(boolean enable) {
         if (skill.equalsIgnoreCase("ALL")) {
-            for (SkillType skillType : SkillType.nonChildSkills()) {
+            for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
                 skillType.setHardcoreStatLossEnabled(enable);
             }
         }

+ 1 - 1
src/main/java/com/gmail/nossr50/commands/hardcore/VampirismCommand.java

@@ -50,7 +50,7 @@ public class VampirismCommand extends HardcoreModeCommand {
 
     private void toggle(boolean enable) {
         if (skill.equalsIgnoreCase("ALL")) {
-            for (SkillType skillType : SkillType.nonChildSkills()) {
+            for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
                 skillType.setHardcoreVampirismEnabled(enable);
             }
         }

+ 10 - 12
src/main/java/com/gmail/nossr50/commands/player/InspectCommand.java

@@ -52,22 +52,20 @@ public class InspectCommand implements TabExecutor {
                     sender.sendMessage(LocaleLoader.getString("Inspect.OfflineStats", playerName));
 
                     sender.sendMessage(LocaleLoader.getString("Stats.Header.Gathering"));
-                    CommandUtils.displaySkill(sender, profile, SkillType.EXCAVATION);
-                    CommandUtils.displaySkill(sender, profile, SkillType.FISHING);
-                    CommandUtils.displaySkill(sender, profile, SkillType.HERBALISM);
-                    CommandUtils.displaySkill(sender, profile, SkillType.MINING);
-                    CommandUtils.displaySkill(sender, profile, SkillType.WOODCUTTING);
+                    for (SkillType skill : SkillType.GATHERING_SKILLS) {
+                        sender.sendMessage(CommandUtils.displaySkill(profile, skill));
+                    }
 
                     sender.sendMessage(LocaleLoader.getString("Stats.Header.Combat"));
-                    CommandUtils.displaySkill(sender, profile, SkillType.AXES);
-                    CommandUtils.displaySkill(sender, profile, SkillType.ARCHERY);
-                    CommandUtils.displaySkill(sender, profile, SkillType.SWORDS);
-                    CommandUtils.displaySkill(sender, profile, SkillType.TAMING);
-                    CommandUtils.displaySkill(sender, profile, SkillType.UNARMED);
+                    for (SkillType skill : SkillType.COMBAT_SKILLS) {
+                        sender.sendMessage(CommandUtils.displaySkill(profile, skill));
+                    }
 
                     sender.sendMessage(LocaleLoader.getString("Stats.Header.Misc"));
-                    CommandUtils.displaySkill(sender, profile, SkillType.ACROBATICS);
-                    CommandUtils.displaySkill(sender, profile, SkillType.REPAIR);
+                    for (SkillType skill : SkillType.MISC_SKILLS) {
+                        sender.sendMessage(CommandUtils.displaySkill(profile, skill));
+                    }
+
                 }
                 else {
                     Player target = mcMMOPlayer.getPlayer();

+ 2 - 3
src/main/java/com/gmail/nossr50/commands/skills/SkillCommand.java

@@ -23,7 +23,6 @@ import com.gmail.nossr50.util.commands.CommandUtils;
 import com.gmail.nossr50.util.player.UserManager;
 import com.gmail.nossr50.util.scoreboards.ScoreboardManager;
 import com.gmail.nossr50.util.skills.PerksUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 
 import com.google.common.collect.ImmutableList;
 
@@ -46,7 +45,7 @@ public abstract class SkillCommand implements TabExecutor {
 
     public SkillCommand(SkillType skill) {
         this.skill = skill;
-        skillName = SkillUtils.getSkillName(skill);
+        skillName = skill.getSkillName();
         skillGuideCommand = new SkillGuideCommand(skill);
     }
 
@@ -91,7 +90,7 @@ public abstract class SkillCommand implements TabExecutor {
                     Set<SkillType> parents = FamilyTree.getParents(skill);
 
                     for (SkillType parent : parents) {
-                        player.sendMessage(SkillUtils.getSkillName(parent) + " - " + LocaleLoader.getString("Effects.Level", profile.getSkillLevel(parent), profile.getSkillXpLevel(parent), profile.getXpToLevel(parent)));
+                        player.sendMessage(parent.getSkillName() + " - " + LocaleLoader.getString("Effects.Level", profile.getSkillLevel(parent), profile.getSkillXpLevel(parent), profile.getXpToLevel(parent)));
                     }
                 }
 

+ 1 - 2
src/main/java/com/gmail/nossr50/commands/skills/SkillGuideCommand.java

@@ -10,7 +10,6 @@ import org.bukkit.command.CommandSender;
 import com.gmail.nossr50.datatypes.skills.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.StringUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 
 public class SkillGuideCommand implements CommandExecutor {
     private String header;
@@ -19,7 +18,7 @@ public class SkillGuideCommand implements CommandExecutor {
     private String invalidPage;
 
     public SkillGuideCommand(SkillType skillType) {
-        header = LocaleLoader.getString("Guides.Header", SkillUtils.getSkillName(skillType));
+        header = LocaleLoader.getString("Guides.Header", skillType.getSkillName());
         guide = getGuide(skillType);
 
         invalidPage = LocaleLoader.getString("Guides.Page.Invalid");

+ 1 - 1
src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java

@@ -299,7 +299,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
 
         Map<String, Integer> skills = new HashMap<String, Integer>();
 
-        for (SkillType skill : SkillType.nonChildSkills()) {
+        for (SkillType skill : SkillType.NON_CHILD_SKILLS) {
             skills.put(skill.name(), getPlayerRank(playerName, playerStatHash.get(skill)));
         }
 

+ 1 - 1
src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java

@@ -237,7 +237,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
             ResultSet resultSet;
 
             try {
-                for (SkillType skillType : SkillType.nonChildSkills()) {
+                for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
                     String skillName = skillType.name().toLowerCase();
                     String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " +
                                  "AND " + skillName + " > (SELECT " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +

+ 147 - 2
src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java

@@ -9,10 +9,13 @@ import org.bukkit.GameMode;
 import org.bukkit.Location;
 import org.bukkit.Material;
 import org.bukkit.Server;
+import org.bukkit.Sound;
 import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
 import org.bukkit.scheduler.BukkitRunnable;
 
 import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.datatypes.mods.CustomTool;
@@ -25,6 +28,7 @@ import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.party.PartyManager;
 import com.gmail.nossr50.party.ShareHandler;
 import com.gmail.nossr50.runnables.skills.AbilityDisableTask;
+import com.gmail.nossr50.runnables.skills.ToolLowerTask;
 import com.gmail.nossr50.skills.SkillManager;
 import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
 import com.gmail.nossr50.skills.archery.ArcheryManager;
@@ -41,9 +45,12 @@ import com.gmail.nossr50.skills.swords.SwordsManager;
 import com.gmail.nossr50.skills.taming.TamingManager;
 import com.gmail.nossr50.skills.unarmed.UnarmedManager;
 import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager;
+import com.gmail.nossr50.util.EventUtils;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.ModUtils;
 import com.gmail.nossr50.util.Permissions;
+import com.gmail.nossr50.util.StringUtils;
+import com.gmail.nossr50.util.skills.ParticleEffectUtils;
 import com.gmail.nossr50.util.skills.PerksUtils;
 import com.gmail.nossr50.util.skills.SkillUtils;
 
@@ -514,7 +521,7 @@ public class McMMOPlayer {
     public int getPowerLevel() {
         int powerLevel = 0;
 
-        for (SkillType type : SkillType.nonChildSkills()) {
+        for (SkillType type : SkillType.NON_CHILD_SKILLS) {
             if (Permissions.skillEnabled(player, type)) {
                 powerLevel += profile.getSkillLevel(type);
             }
@@ -597,7 +604,42 @@ public class McMMOPlayer {
         profile.setSkillXpLevel(skillType, profile.getSkillXpLevelRaw(skillType) + event.getRawXpGained());
 
         isUsingUnarmed = (skillType == SkillType.UNARMED);
-        SkillUtils.xpCheckSkill(skillType, player, profile);
+        checkXp(skillType);
+    }
+
+    /**
+     * Check the XP of a skill.
+     *
+     * @param skillType The skill to check
+     */
+    private void checkXp(SkillType skillType) {
+        int levelsGained = 0;
+        float xpRemoved = 0;
+
+        if (profile.getSkillXpLevelRaw(skillType) >= profile.getXpToLevel(skillType)) {
+            while (profile.getSkillXpLevelRaw(skillType) >= profile.getXpToLevel(skillType)) {
+                if ((skillType.getMaxLevel() >= profile.getSkillLevel(skillType) + 1) && (Config.getInstance().getPowerLevelCap() >= getPowerLevel() + 1)) {
+                    int xp = profile.getXpToLevel(skillType);
+                    xpRemoved += xp;
+
+                    profile.removeXp(skillType, xp);
+                    levelsGained++;
+                    profile.skillUp(skillType, 1);
+                }
+                else {
+                    profile.addLevels(skillType, 0);
+                }
+            }
+
+            if (EventUtils.callLevelUpEvent(player, skillType, levelsGained).isCancelled()) {
+                profile.modifySkill(skillType, profile.getSkillLevel(skillType) - levelsGained);
+                profile.setSkillXpLevel(skillType, profile.getSkillXpLevelRaw(skillType) + xpRemoved);
+                return;
+            }
+
+            player.playSound(player.getLocation(), Sound.LEVEL_UP, Misc.LEVELUP_VOLUME, Misc.LEVELUP_PITCH);
+            player.sendMessage(LocaleLoader.getString(StringUtils.getCapitalized(skillType.toString()) + ".Skillup", levelsGained, profile.getSkillLevel(skillType)));
+        }
     }
 
     /*
@@ -782,4 +824,107 @@ public class McMMOPlayer {
             player.sendMessage(LocaleLoader.getString("Party.Forbidden"));
         }
     }
+
+    /**
+     * Check to see if an ability can be activated.
+     *
+     * @param skill The skill the ability is based on
+     */
+    public void checkAbilityActivation(SkillType skill) {
+        ToolType tool = skill.getTool();
+        AbilityType ability = skill.getAbility();
+
+        setToolPreparationMode(tool, false);
+
+        if (!getAbilityMode(ability)) {
+            return;
+        }
+
+        int timeRemaining = SkillUtils.calculateTimeLeft(profile.getSkillDATS(ability) * Misc.TIME_CONVERSION_FACTOR, ability.getCooldown(), player);
+
+        if (timeRemaining > 0) {
+            /*
+             * Axes and Woodcutting are odd because they share the same tool.
+             * We show them the too tired message when they take action.
+             */
+            if (skill == SkillType.WOODCUTTING || skill == SkillType.AXES) {
+                player.sendMessage(LocaleLoader.getString("Skills.TooTired", timeRemaining));
+            }
+
+            return;
+        }
+
+        if (EventUtils.callPlayerAbilityActivateEvent(player, skill).isCancelled()) {
+            return;
+        }
+
+        int ticks = PerksUtils.handleActivationPerks(player, 2 + (profile.getSkillLevel(skill) / AdvancedConfig.getInstance().getAbilityLength()), ability.getMaxLength());
+
+        // Notify people that ability has been activated
+        ParticleEffectUtils.playAbilityEnabledEffect(player);
+
+        if (useChatNotifications()) {
+            player.sendMessage(ability.getAbilityOn());
+        }
+
+        SkillUtils.sendSkillMessage(player, ability.getAbilityPlayer(player));
+
+        // Enable the ability
+        profile.setSkillDATS(ability, System.currentTimeMillis() + (ticks * Misc.TIME_CONVERSION_FACTOR));
+        setAbilityMode(ability, true);
+
+        if (ability == AbilityType.SUPER_BREAKER || ability == AbilityType.GIGA_DRILL_BREAKER) {
+            SkillUtils.handleAbilitySpeedIncrease(player);
+        }
+
+        new AbilityDisableTask(this, ability).runTaskLater(mcMMO.p, ticks * Misc.TICK_CONVERSION_FACTOR);
+    }
+
+    public void processAbilityActivation(SkillType skill) {
+        if (Config.getInstance().getAbilitiesOnlyActivateWhenSneaking() && !player.isSneaking()) {
+            return;
+        }
+
+        ItemStack inHand = player.getItemInHand();
+
+        if (ModUtils.isCustomTool(inHand) && !ModUtils.getToolFromItemStack(inHand).isAbilityEnabled()) {
+            return;
+        }
+
+        if (!getAbilityUse()) {
+            return;
+        }
+
+        for (AbilityType abilityType : AbilityType.values()) {
+            if (getAbilityMode(abilityType)) {
+                return;
+            }
+        }
+
+        AbilityType ability = skill.getAbility();
+        ToolType tool = skill.getTool();
+
+        /*
+         * Woodcutting & Axes need to be treated differently.
+         * Basically the tool always needs to ready and we check to see if the cooldown is over when the user takes action
+         */
+        if (ability.getPermissions(player) && tool.inHand(inHand) && !getToolPreparationMode(tool)) {
+            if (skill != SkillType.WOODCUTTING && skill != SkillType.AXES) {
+                int timeRemaining = SkillUtils.calculateTimeLeft(profile.getSkillDATS(ability) * Misc.TIME_CONVERSION_FACTOR, ability.getCooldown(), player);
+
+                if (!getAbilityMode(ability) && timeRemaining > 0) {
+                    player.sendMessage(LocaleLoader.getString("Skills.TooTired", timeRemaining));
+                    return;
+                }
+            }
+
+            if (Config.getInstance().getAbilityMessagesEnabled()) {
+                player.sendMessage(tool.getRaiseTool());
+            }
+
+            setToolPreparationATS(tool, System.currentTimeMillis());
+            setToolPreparationMode(tool, true);
+            new ToolLowerTask(this, tool).runTaskLaterAsynchronously(mcMMO.p, 4 * Misc.TICK_CONVERSION_FACTOR);
+        }
+    }
 }

+ 2 - 6
src/main/java/com/gmail/nossr50/datatypes/player/PlayerProfile.java

@@ -39,7 +39,7 @@ public class PlayerProfile {
             skillsDATS.put(abilityType, 0);
         }
 
-        for (SkillType skillType : SkillType.nonChildSkills()) {
+        for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
             skills.put(skillType, 0);
             skillsXp.put(skillType, 0F);
         }
@@ -152,11 +152,7 @@ public class PlayerProfile {
      */
 
     public int getSkillLevel(SkillType skillType) {
-        if (skillType.isChildSkill()) {
-            return getChildSkillLevel(skillType);
-        }
-
-        return skills.get(skillType);
+        return skillType.isChildSkill() ? getChildSkillLevel(skillType) : skills.get(skillType);
     }
 
     public float getSkillXpLevelRaw(SkillType skillType) {

+ 21 - 0
src/main/java/com/gmail/nossr50/datatypes/skills/AbilityType.java

@@ -1,12 +1,14 @@
 package com.gmail.nossr50.datatypes.skills;
 
 import org.bukkit.Material;
+import org.bukkit.block.Block;
 import org.bukkit.block.BlockState;
 import org.bukkit.entity.Player;
 
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.BlockUtils;
+import com.gmail.nossr50.util.EventUtils;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
 
@@ -220,4 +222,23 @@ public enum AbilityType {
                 return false;
         }
     }
+
+    /**
+     * Check to see if ability should be triggered.
+     *
+     * @param player The player using the ability
+     * @param block The block modified by the ability
+     * @return true if the ability should activate, false otherwise
+     */
+    public boolean triggerCheck(Player player, Block block) {
+        switch (this) {
+            case BERSERK:
+            case BLOCK_CRACKER:
+            case LEAF_BLOWER:
+                return blockCheck(block.getState()) && EventUtils.simulateBlockBreak(block, player, true);
+
+            default:
+                return false;
+        }
+    }
 }

+ 28 - 25
src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java

@@ -25,7 +25,6 @@ import com.gmail.nossr50.skills.taming.TamingManager;
 import com.gmail.nossr50.skills.unarmed.UnarmedManager;
 import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager;
 import com.gmail.nossr50.util.StringUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 
 import com.google.common.collect.ImmutableList;
 
@@ -51,15 +50,34 @@ public enum SkillType {
 
     public static final List<String> SKILL_NAMES;
 
+    public static final List<SkillType> CHILD_SKILLS;
+    public static final List<SkillType> NON_CHILD_SKILLS;
+
+    public static final List<SkillType> COMBAT_SKILLS = ImmutableList.of(ARCHERY, AXES, SWORDS, TAMING, UNARMED);
+    public static final List<SkillType> GATHERING_SKILLS = ImmutableList.of(EXCAVATION, FISHING, HERBALISM, MINING, WOODCUTTING);
+    public static final List<SkillType> MISC_SKILLS = ImmutableList.of(ACROBATICS, REPAIR, SMELTING);
+
     static {
+        List<SkillType> childSkills = new ArrayList<SkillType>();
+        List<SkillType> nonChildSkills = new ArrayList<SkillType>();
         ArrayList<String> names = new ArrayList<String>();
 
         for (SkillType skill : values()) {
-            names.add(SkillUtils.getSkillName(skill));
+            if (skill.isChildSkill()) {
+                childSkills.add(skill);
+            }
+            else {
+                nonChildSkills.add(skill);
+            }
+
+            names.add(skill.getSkillName());
         }
 
         Collections.sort(names);
         SKILL_NAMES = ImmutableList.copyOf(names);
+
+        CHILD_SKILLS = ImmutableList.copyOf(childSkills);
+        NON_CHILD_SKILLS = ImmutableList.copyOf(nonChildSkills);
     }
 
     private SkillType(Class<? extends SkillManager> managerClass, Color runescapeColor) {
@@ -151,33 +169,14 @@ public enum SkillType {
     // TODO: This is a little "hacky", we probably need to add something to distinguish child skills in the enum, or to use another enum for them
     public boolean isChildSkill() {
         switch (this) {
-        case SMELTING:
-            return true;
+            case SMELTING:
+                return true;
 
-        default:
-            return false;
+            default:
+                return false;
         }
     }
 
-    public static SkillType[] nonChildSkills() {
-        return new SkillType[] {SkillType.ACROBATICS,
-                SkillType.ARCHERY,
-                SkillType.AXES,
-                SkillType.EXCAVATION,
-                SkillType.FISHING,
-                SkillType.HERBALISM,
-                SkillType.MINING,
-                SkillType.REPAIR,
-                SkillType.SWORDS,
-                SkillType.TAMING,
-                SkillType.UNARMED,
-                SkillType.WOODCUTTING };
-    }
-
-    public static SkillType[] childSkills() {
-        return new SkillType[] { SkillType.SMELTING };
-    }
-
     public Color getRunescapeModeColor() {
         return runescapeColor;
     }
@@ -191,4 +190,8 @@ public enum SkillType {
 
         return null;
     }
+
+    public String getSkillName() {
+        return Config.getInstance().getLocale().equalsIgnoreCase("en_US") ? StringUtils.getCapitalized(this.toString()) : StringUtils.getCapitalized(LocaleLoader.getString(StringUtils.getCapitalized(this.toString()) + ".SkillName"));
+    }
 }

+ 9 - 9
src/main/java/com/gmail/nossr50/listeners/BlockListener.java

@@ -149,7 +149,7 @@ public class BlockListener implements Listener {
 
             /* Green Terra */
             if (herbalismManager.canActivateAbility()) {
-                SkillUtils.abilityCheck(mcMMOPlayer, SkillType.HERBALISM);
+                mcMMOPlayer.checkAbilityActivation(SkillType.HERBALISM);
             }
 
             /*
@@ -280,19 +280,19 @@ public class BlockListener implements Listener {
             }
 
             if (mcMMOPlayer.getToolPreparationMode(ToolType.HOE) && ItemUtils.isHoe(heldItem) && (BlockUtils.affectedByGreenTerra(blockState) || BlockUtils.canMakeMossy(blockState)) && Permissions.greenTerra(player)) {
-                SkillUtils.abilityCheck(mcMMOPlayer, SkillType.HERBALISM);
+                mcMMOPlayer.checkAbilityActivation(SkillType.HERBALISM);
             }
             else if (mcMMOPlayer.getToolPreparationMode(ToolType.AXE) && ItemUtils.isAxe(heldItem) && BlockUtils.isLog(blockState) && Permissions.treeFeller(player)) {
-                SkillUtils.abilityCheck(mcMMOPlayer, SkillType.WOODCUTTING);
+                mcMMOPlayer.checkAbilityActivation(SkillType.WOODCUTTING);
             }
             else if (mcMMOPlayer.getToolPreparationMode(ToolType.PICKAXE) && ItemUtils.isPickaxe(heldItem) && BlockUtils.affectedBySuperBreaker(blockState) && Permissions.superBreaker(player)) {
-                SkillUtils.abilityCheck(mcMMOPlayer, SkillType.MINING);
+                mcMMOPlayer.checkAbilityActivation(SkillType.MINING);
             }
             else if (mcMMOPlayer.getToolPreparationMode(ToolType.SHOVEL) && ItemUtils.isShovel(heldItem) && BlockUtils.affectedByGigaDrillBreaker(blockState) && Permissions.gigaDrillBreaker(player)) {
-                SkillUtils.abilityCheck(mcMMOPlayer, SkillType.EXCAVATION);
+                mcMMOPlayer.checkAbilityActivation(SkillType.EXCAVATION);
             }
             else if (mcMMOPlayer.getToolPreparationMode(ToolType.FISTS) && heldItem.getType() == Material.AIR && (BlockUtils.affectedByGigaDrillBreaker(blockState) || blockState.getType() == Material.SNOW || BlockUtils.affectedByBlockCracker(blockState) && Permissions.berserk(player))) {
-                SkillUtils.abilityCheck(mcMMOPlayer, SkillType.UNARMED);
+                mcMMOPlayer.checkAbilityActivation(SkillType.UNARMED);
             }
         }
 
@@ -339,17 +339,17 @@ public class BlockListener implements Listener {
             }
         }
         else if (mcMMOPlayer.getAbilityMode(AbilityType.BERSERK) && heldItem.getType() == Material.AIR) {
-            if (SkillUtils.triggerCheck(player, block, AbilityType.BERSERK)) {
+            if (AbilityType.BERSERK.triggerCheck(player, block)) {
                 event.setInstaBreak(true);
                 player.playSound(block.getLocation(), Sound.ITEM_PICKUP, Misc.POP_VOLUME, Misc.getPopPitch());
             }
-            else if (mcMMOPlayer.getUnarmedManager().canUseBlockCracker() && SkillUtils.triggerCheck(player, block, AbilityType.BLOCK_CRACKER)) {
+            else if (mcMMOPlayer.getUnarmedManager().canUseBlockCracker() && AbilityType.BLOCK_CRACKER.triggerCheck(player, block)) {
                 if (mcMMOPlayer.getUnarmedManager().blockCrackerCheck(blockState)) {
                     blockState.update();
                 }
             }
         }
-        else if (mcMMOPlayer.getWoodcuttingManager().canUseLeafBlower(heldItem) && SkillUtils.triggerCheck(player, block, AbilityType.LEAF_BLOWER)) {
+        else if (mcMMOPlayer.getWoodcuttingManager().canUseLeafBlower(heldItem) && AbilityType.LEAF_BLOWER.triggerCheck(player, block)) {
             event.setInstaBreak(true);
             player.playSound(blockState.getLocation(), Sound.ITEM_PICKUP, Misc.POP_VOLUME, Misc.getPopPitch());
         }

+ 18 - 17
src/main/java/com/gmail/nossr50/listeners/PlayerListener.java

@@ -49,6 +49,7 @@ import com.gmail.nossr50.skills.taming.TamingManager;
 import com.gmail.nossr50.skills.unarmed.Unarmed;
 import com.gmail.nossr50.util.BlockUtils;
 import com.gmail.nossr50.util.ChimaeraWing;
+import com.gmail.nossr50.util.EventUtils;
 import com.gmail.nossr50.util.HardcoreManager;
 import com.gmail.nossr50.util.ItemUtils;
 import com.gmail.nossr50.util.Misc;
@@ -514,15 +515,15 @@ public class PlayerListener implements Listener {
                 if (BlockUtils.canActivateAbilities(blockState)) {
                     if (Config.getInstance().getAbilitiesEnabled()) {
                         if (BlockUtils.canActivateHerbalism(blockState)) {
-                            SkillUtils.activationCheck(player, SkillType.HERBALISM);
+                            mcMMOPlayer.processAbilityActivation(SkillType.HERBALISM);
                         }
 
-                        SkillUtils.activationCheck(player, SkillType.AXES);
-                        SkillUtils.activationCheck(player, SkillType.EXCAVATION);
-                        SkillUtils.activationCheck(player, SkillType.MINING);
-                        SkillUtils.activationCheck(player, SkillType.SWORDS);
-                        SkillUtils.activationCheck(player, SkillType.UNARMED);
-                        SkillUtils.activationCheck(player, SkillType.WOODCUTTING);
+                        mcMMOPlayer.processAbilityActivation(SkillType.AXES);
+                        mcMMOPlayer.processAbilityActivation(SkillType.EXCAVATION);
+                        mcMMOPlayer.processAbilityActivation(SkillType.MINING);
+                        mcMMOPlayer.processAbilityActivation(SkillType.SWORDS);
+                        mcMMOPlayer.processAbilityActivation(SkillType.UNARMED);
+                        mcMMOPlayer.processAbilityActivation(SkillType.WOODCUTTING);
                     }
 
                     ChimaeraWing.activationCheck(player);
@@ -534,14 +535,14 @@ public class PlayerListener implements Listener {
                 if (herbalismManager.canGreenThumbBlock(blockState)) {
                     player.setItemInHand(new ItemStack(Material.SEEDS, heldItem.getAmount() - 1));
 
-                    if (herbalismManager.processGreenThumbBlocks(blockState) && SkillUtils.blockBreakSimulate(block, player, false)) {
+                    if (herbalismManager.processGreenThumbBlocks(blockState) && EventUtils.simulateBlockBreak(block, player, false)) {
                         blockState.update(true);
                     }
                 }
 
                 /* SHROOM THUMB CHECK */
                 else if (herbalismManager.canUseShroomThumb(blockState)) {
-                    if (herbalismManager.processShroomThumb(blockState) && SkillUtils.blockBreakSimulate(block, player, false)) {
+                    if (herbalismManager.processShroomThumb(blockState) && EventUtils.simulateBlockBreak(block, player, false)) {
                         blockState.update(true);
                     }
                 }
@@ -551,13 +552,13 @@ public class PlayerListener implements Listener {
 
                 /* ACTIVATION CHECKS */
                 if (Config.getInstance().getAbilitiesEnabled()) {
-                    SkillUtils.activationCheck(player, SkillType.AXES);
-                    SkillUtils.activationCheck(player, SkillType.EXCAVATION);
-                    SkillUtils.activationCheck(player, SkillType.HERBALISM);
-                    SkillUtils.activationCheck(player, SkillType.MINING);
-                    SkillUtils.activationCheck(player, SkillType.SWORDS);
-                    SkillUtils.activationCheck(player, SkillType.UNARMED);
-                    SkillUtils.activationCheck(player, SkillType.WOODCUTTING);
+                    mcMMOPlayer.processAbilityActivation(SkillType.AXES);
+                    mcMMOPlayer.processAbilityActivation(SkillType.EXCAVATION);
+                    mcMMOPlayer.processAbilityActivation(SkillType.HERBALISM);
+                    mcMMOPlayer.processAbilityActivation(SkillType.MINING);
+                    mcMMOPlayer.processAbilityActivation(SkillType.SWORDS);
+                    mcMMOPlayer.processAbilityActivation(SkillType.UNARMED);
+                    mcMMOPlayer.processAbilityActivation(SkillType.WOODCUTTING);
                 }
 
                 /* ITEM CHECKS */
@@ -659,7 +660,7 @@ public class PlayerListener implements Listener {
             // Do these ACTUALLY have to be lower case to work properly?
             for (SkillType skill : SkillType.values()) {
                 String skillName = skill.toString().toLowerCase();
-                String localizedName = SkillUtils.getSkillName(skill).toLowerCase();
+                String localizedName = skill.getSkillName().toLowerCase();
 
                 if (lowerCaseCommand.equals(localizedName)) {
                     event.setMessage(message.replace(command, skillName));

+ 2 - 3
src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java

@@ -10,7 +10,6 @@ import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.datatypes.skills.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.Permissions;
-import com.gmail.nossr50.util.skills.SkillUtils;
 
 public class McrankCommandDisplayTask extends BukkitRunnable {
     private final Map<String, Integer> skills;
@@ -31,13 +30,13 @@ public class McrankCommandDisplayTask extends BukkitRunnable {
         sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Heading"));
         sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Player", playerName));
 
-        for (SkillType skill : SkillType.nonChildSkills()) {
+        for (SkillType skill : SkillType.NON_CHILD_SKILLS) {
             if (player != null && !Permissions.skillEnabled(player, skill)) {
                 continue;
             }
 
             rank = skills.get(skill.name());
-            sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", SkillUtils.getSkillName(skill), (rank == null ? LocaleLoader.getString("Commands.mcrank.Unranked") : rank)));
+            sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", skill.getSkillName(), (rank == null ? LocaleLoader.getString("Commands.mcrank.Unranked") : rank)));
         }
 
         rank = skills.get("ALL");

+ 1 - 1
src/main/java/com/gmail/nossr50/runnables/database/FormulaConversionTask.java

@@ -52,7 +52,7 @@ public class FormulaConversionTask extends BukkitRunnable {
     private void editValues(PlayerProfile profile) {
         mcMMO.p.debug("========================================================================");
         mcMMO.p.debug("Conversion report for " + profile.getPlayerName() + ":");
-        for (SkillType skillType : SkillType.nonChildSkills()) {
+        for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
             int oldLevel = profile.getSkillLevel(skillType);
             int oldXPLevel = profile.getSkillXpLevel(skillType);
             int totalOldXP = mcMMO.getFormulaManager().calculateTotalExperience(oldLevel, oldXPLevel);

+ 1 - 1
src/main/java/com/gmail/nossr50/skills/child/ChildConfig.java

@@ -20,7 +20,7 @@ public class ChildConfig extends AutoUpdateConfigLoader {
 
         FamilyTree.clearRegistrations(); // when reloading, need to clear statics
 
-        for (SkillType skill : SkillType.childSkills()) {
+        for (SkillType skill : SkillType.CHILD_SKILLS) {
             plugin.debug("Finding parents of " + skill.name());
 
             EnumSet<SkillType> parentSkills = EnumSet.noneOf(SkillType.class);

+ 2 - 1
src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java

@@ -22,6 +22,7 @@ import com.gmail.nossr50.runnables.skills.AbilityCooldownTask;
 import com.gmail.nossr50.skills.SkillManager;
 import com.gmail.nossr50.skills.mining.BlastMining.Tier;
 import com.gmail.nossr50.util.BlockUtils;
+import com.gmail.nossr50.util.EventUtils;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.ModUtils;
 import com.gmail.nossr50.util.Permissions;
@@ -95,7 +96,7 @@ public class MiningManager extends SkillManager {
         Player player = getPlayer();
         Block targetBlock = player.getTargetBlock(BlockUtils.getTransparentBlocks(), BlastMining.MAXIMUM_REMOTE_DETONATION_DISTANCE);
 
-        if (targetBlock.getType() != Material.TNT || !SkillUtils.blockBreakSimulate(targetBlock, player, true) || !blastMiningCooldownOver()) {
+        if (targetBlock.getType() != Material.TNT || !EventUtils.simulateBlockBreak(targetBlock, player, true) || !blastMiningCooldownOver()) {
             return;
         }
 

+ 2 - 1
src/main/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingManager.java

@@ -18,6 +18,7 @@ import com.gmail.nossr50.datatypes.skills.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.SkillManager;
 import com.gmail.nossr50.skills.woodcutting.Woodcutting.ExperienceGainMethod;
+import com.gmail.nossr50.util.EventUtils;
 import com.gmail.nossr50.util.ItemUtils;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.ModUtils;
@@ -129,7 +130,7 @@ public class WoodcuttingManager extends SkillManager {
         for (BlockState blockState : treeFellerBlocks) {
             Block block = blockState.getBlock();
 
-            if (!SkillUtils.blockBreakSimulate(block, player, true)) {
+            if (!EventUtils.simulateBlockBreak(block, player, true)) {
                 break; // TODO: Shouldn't we use continue instead?
             }
 

+ 62 - 0
src/main/java/com/gmail/nossr50/util/EventUtils.java

@@ -0,0 +1,62 @@
+package com.gmail.nossr50.util;
+
+import org.bukkit.block.Block;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.PluginManager;
+
+import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.datatypes.skills.SkillType;
+import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent;
+import com.gmail.nossr50.events.fake.FakeBlockBreakEvent;
+import com.gmail.nossr50.events.fake.FakeBlockDamageEvent;
+import com.gmail.nossr50.events.fake.FakePlayerAnimationEvent;
+import com.gmail.nossr50.events.skills.abilities.McMMOPlayerAbilityActivateEvent;
+
+public class EventUtils {
+    public static McMMOPlayerAbilityActivateEvent callPlayerAbilityActivateEvent(Player player, SkillType skill) {
+        McMMOPlayerAbilityActivateEvent event = new McMMOPlayerAbilityActivateEvent(player, skill);
+        mcMMO.p.getServer().getPluginManager().callEvent(event);
+
+        return event;
+    }
+
+    public static FakePlayerAnimationEvent callFakeArmSwingEvent(Player player) {
+        FakePlayerAnimationEvent event = new FakePlayerAnimationEvent(player);
+        mcMMO.p.getServer().getPluginManager().callEvent(event);
+
+        return event;
+    }
+
+    public static McMMOPlayerLevelUpEvent callLevelUpEvent(Player player, SkillType skill, int levelsGained) {
+        McMMOPlayerLevelUpEvent event = new McMMOPlayerLevelUpEvent(player, skill, levelsGained);
+        mcMMO.p.getServer().getPluginManager().callEvent(event);
+
+        return event;
+    }
+
+    /**
+     * Simulate a block break event.
+     *
+     * @param block The block to break
+     * @param player The player breaking the block
+     * @param shouldArmSwing true if an armswing event should be fired, false otherwise
+     * @return true if the event wasn't cancelled, false otherwise
+     */
+    public static boolean simulateBlockBreak(Block block, Player player, boolean shouldArmSwing) {
+        PluginManager pluginManager = mcMMO.p.getServer().getPluginManager();
+
+        // Support for NoCheat
+        if (shouldArmSwing) {
+            callFakeArmSwingEvent(player);
+        }
+
+        FakeBlockDamageEvent damageEvent = new FakeBlockDamageEvent(player, block, player.getItemInHand(), true);
+        pluginManager.callEvent(damageEvent);
+
+        FakeBlockBreakEvent breakEvent = new FakeBlockBreakEvent(block, player);
+        pluginManager.callEvent(breakEvent);
+
+        return !damageEvent.isCancelled() && !breakEvent.isCancelled();
+    }
+}
+

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

@@ -26,7 +26,7 @@ public final class HardcoreManager {
         PlayerProfile playerProfile = UserManager.getPlayer(player).getProfile();
         int totalLost = 0;
 
-        for (SkillType skillType : SkillType.nonChildSkills()) {
+        for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
             int playerSkillLevel = playerProfile.getSkillLevel(skillType);
 
             if (playerSkillLevel <= 0) {
@@ -56,7 +56,7 @@ public final class HardcoreManager {
         PlayerProfile victimProfile = UserManager.getPlayer(victim).getProfile();
         int totalStolen = 0;
 
-        for (SkillType skillType : SkillType.nonChildSkills()) {
+        for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
             int killerSkillLevel = killerProfile.getSkillLevel(skillType);
             int victimSkillLevel = victimProfile.getSkillLevel(skillType);
 
@@ -89,7 +89,7 @@ public final class HardcoreManager {
     public static boolean isStatLossEnabled() {
         boolean enabled = false;
 
-        for (SkillType skillType : SkillType.nonChildSkills()) {
+        for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
             if (skillType.getHardcoreStatLossEnabled()) {
                 enabled = true;
                 break;
@@ -107,7 +107,7 @@ public final class HardcoreManager {
     public static boolean isVampirismEnabled() {
         boolean enabled = false;
 
-        for (SkillType skillType : SkillType.nonChildSkills()) {
+        for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
             if (skillType.getHardcoreVampirismEnabled()) {
                 enabled = true;
                 break;

+ 1 - 2
src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java

@@ -50,7 +50,6 @@ import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.skills.SkillType;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.util.StringUtils;
-import com.gmail.nossr50.util.skills.SkillUtils;
 
 public final class CommandRegistrationManager {
     private CommandRegistrationManager() {};
@@ -60,7 +59,7 @@ public final class CommandRegistrationManager {
     private static void registerSkillCommands() {
         for (SkillType skill : SkillType.values()) {
             String commandName = skill.toString().toLowerCase();
-            String localizedName = SkillUtils.getSkillName(skill).toLowerCase();
+            String localizedName = skill.getSkillName().toLowerCase();
 
             PluginCommand command;
 

+ 27 - 32
src/main/java/com/gmail/nossr50/util/commands/CommandUtils.java

@@ -1,5 +1,6 @@
 package com.gmail.nossr50.util.commands;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.bukkit.OfflinePlayer;
@@ -157,16 +158,7 @@ public final class CommandUtils {
      * @param display The sender to display stats to
      */
     public static void printGatheringSkills(Player inspect, CommandSender display) {
-        if (SkillUtils.hasGatheringSkills(inspect)) {
-            PlayerProfile profile = UserManager.getPlayer(inspect).getProfile();
-
-            display.sendMessage(LocaleLoader.getString("Stats.Header.Gathering"));
-            displaySkill(inspect, profile, SkillType.EXCAVATION, display);
-            displaySkill(inspect, profile, SkillType.FISHING, display);
-            displaySkill(inspect, profile, SkillType.HERBALISM, display);
-            displaySkill(inspect, profile, SkillType.MINING, display);
-            displaySkill(inspect, profile, SkillType.WOODCUTTING, display);
-        }
+        printGroupedSkillData(inspect, display, LocaleLoader.getString("Stats.Header.Gathering"), SkillType.GATHERING_SKILLS);
     }
 
     public static void printGatheringSkills(Player player) {
@@ -180,16 +172,7 @@ public final class CommandUtils {
      * @param display The sender to display stats to
      */
     public static void printCombatSkills(Player inspect, CommandSender display) {
-        if (SkillUtils.hasCombatSkills(inspect)) {
-            PlayerProfile profile = UserManager.getPlayer(inspect).getProfile();
-
-            display.sendMessage(LocaleLoader.getString("Stats.Header.Combat"));
-            displaySkill(inspect, profile, SkillType.AXES, display);
-            displaySkill(inspect, profile, SkillType.ARCHERY, display);
-            displaySkill(inspect, profile, SkillType.SWORDS, display);
-            displaySkill(inspect, profile, SkillType.TAMING, display);
-            displaySkill(inspect, profile, SkillType.UNARMED, display);
-        }
+        printGroupedSkillData(inspect, display, LocaleLoader.getString("Stats.Header.Combat"), SkillType.COMBAT_SKILLS);
     }
 
     public static void printCombatSkills(Player player) {
@@ -203,26 +186,38 @@ public final class CommandUtils {
      * @param display The sender to display stats to
      */
     public static void printMiscSkills(Player inspect, CommandSender display) {
-        if (SkillUtils.hasMiscSkills(inspect)) {
-            PlayerProfile profile = UserManager.getPlayer(inspect).getProfile();
-
-            display.sendMessage(LocaleLoader.getString("Stats.Header.Misc"));
-            displaySkill(inspect, profile, SkillType.ACROBATICS, display);
-            displaySkill(inspect, profile, SkillType.REPAIR, display);
-        }
+        printGroupedSkillData(inspect, display, LocaleLoader.getString("Stats.Header.Misc"), SkillType.MISC_SKILLS);
     }
 
     public static void printMiscSkills(Player player) {
         printMiscSkills(player, player);
     }
 
-    private static void displaySkill(Player player, PlayerProfile profile, SkillType skill, CommandSender display) {
-        if (Permissions.skillEnabled(player, skill)) {
-            displaySkill(display, profile, skill);
+    public static String displaySkill(PlayerProfile profile, SkillType skill) {
+        if (skill.isChildSkill()) {
+            return LocaleLoader.getString("Skills.ChildStats", LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".Listener"), profile.getSkillLevel(skill));
         }
+
+        return LocaleLoader.getString("Skills.Stats", LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".Listener"), profile.getSkillLevel(skill), profile.getSkillXpLevel(skill), profile.getXpToLevel(skill));
     }
 
-    public static void displaySkill(CommandSender sender, PlayerProfile profile, SkillType skill) {
-        sender.sendMessage(LocaleLoader.getString("Skills.Stats", LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".Listener"), profile.getSkillLevel(skill), profile.getSkillXpLevel(skill), profile.getXpToLevel(skill)));
+    private static void printGroupedSkillData(Player inspect, CommandSender display, String header, List<SkillType> skillGroup) {
+        PlayerProfile profile = UserManager.getPlayer(inspect).getProfile();
+
+        List<String> displayData = new ArrayList<String>();
+        displayData.add(header);
+
+        for (SkillType skill : skillGroup) {
+            if (Permissions.skillEnabled(inspect, skill)) {
+                displayData.add(displaySkill(profile, skill));
+            }
+        }
+
+        int size = displayData.size();
+
+        if (size > 1) {
+            display.sendMessage(displayData.toArray(new String[size]));
+        }
     }
+
 }

+ 13 - 14
src/main/java/com/gmail/nossr50/util/scoreboards/ScoreboardManager.java

@@ -23,7 +23,6 @@ import com.gmail.nossr50.runnables.scoreboards.ScoreboardChangeTask;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.player.UserManager;
-import com.gmail.nossr50.util.skills.SkillUtils;
 
 public class ScoreboardManager {
     private static final Map<String, Scoreboard> PLAYER_SCOREBOARDS = new HashMap<String, Scoreboard>();
@@ -80,10 +79,10 @@ public class ScoreboardManager {
         Player player = mcMMOPlayer.getPlayer();
         Scoreboard oldScoreboard = player.getScoreboard();
         Scoreboard newScoreboard = PLAYER_SCOREBOARDS.get(player.getName());
-        Objective objective = newScoreboard.getObjective(SkillUtils.getSkillName(skill));
+        Objective objective = newScoreboard.getObjective(skill.getSkillName());
 
         if (objective == null) {
-            objective = newScoreboard.registerNewObjective(SkillUtils.getSkillName(skill), "dummy");
+            objective = newScoreboard.registerNewObjective(skill.getSkillName(), "dummy");
         }
 
         updatePlayerSkillScores(mcMMOPlayer.getProfile(), skill, objective);
@@ -165,7 +164,7 @@ public class ScoreboardManager {
         }
 
         Objective newObjective = GLOBAL_STATS_SCOREBOARD.registerNewObjective(skillName, "dummy");
-        newObjective.setDisplayName(ChatColor.GOLD + (skillName.equalsIgnoreCase("all") ? POWER_LEVEL : SkillUtils.getSkillName(SkillType.getSkill(skillName))));
+        newObjective.setDisplayName(ChatColor.GOLD + (skillName.equalsIgnoreCase("all") ? POWER_LEVEL : SkillType.getSkill(skillName).getSkillName()));
 
         updateGlobalStatsScores(player, newObjective, skillName, pageNumber);
         changeScoreboard(player, oldScoreboard, GLOBAL_STATS_SCOREBOARD, Config.getInstance().getMctopScoreboardTime());
@@ -187,12 +186,12 @@ public class ScoreboardManager {
         PlayerProfile profile = mcMMOPlayer.getProfile();
         Server server = mcMMO.p.getServer();
 
-        for (SkillType skill : SkillType.nonChildSkills()) {
+        for (SkillType skill : SkillType.NON_CHILD_SKILLS) {
             if (!Permissions.skillEnabled(player, skill)) {
                 continue;
             }
 
-            objective.getScore(server.getOfflinePlayer(SkillUtils.getSkillName(skill))).setScore(profile.getSkillLevel(skill));
+            objective.getScore(server.getOfflinePlayer(skill.getSkillName())).setScore(profile.getSkillLevel(skill));
         }
 
         objective.getScore(server.getOfflinePlayer(ChatColor.GOLD + POWER_LEVEL)).setScore(mcMMOPlayer.getPowerLevel());
@@ -206,7 +205,7 @@ public class ScoreboardManager {
 
         Map<String, Integer> skills = mcMMO.getDatabaseManager().readRank(playerName);
 
-        for (SkillType skill : SkillType.nonChildSkills()) {
+        for (SkillType skill : SkillType.NON_CHILD_SKILLS) {
             if (!Permissions.skillEnabled(player, skill)) {
                 continue;
             }
@@ -214,7 +213,7 @@ public class ScoreboardManager {
             rank = skills.get(skill.name());
 
             if (rank != null) {
-                objective.getScore(server.getOfflinePlayer(SkillUtils.getSkillName(skill))).setScore(rank);
+                objective.getScore(server.getOfflinePlayer(skill.getSkillName())).setScore(rank);
             }
         }
 
@@ -233,11 +232,11 @@ public class ScoreboardManager {
 
         Map<String, Integer> skills = mcMMO.getDatabaseManager().readRank(targetName);
 
-        for (SkillType skill : SkillType.nonChildSkills()) {
+        for (SkillType skill : SkillType.NON_CHILD_SKILLS) {
             rank = skills.get(skill.name());
 
             if (rank != null) {
-                objective.getScore(server.getOfflinePlayer(SkillUtils.getSkillName(skill))).setScore(rank);
+                objective.getScore(server.getOfflinePlayer(skill.getSkillName())).setScore(rank);
             }
         }
 
@@ -258,13 +257,13 @@ public class ScoreboardManager {
         int powerLevel = 0;
         int skillLevel;
 
-        for (SkillType skill : SkillType.nonChildSkills()) {
+        for (SkillType skill : SkillType.NON_CHILD_SKILLS) {
             if (!Permissions.skillEnabled(target, skill)) {
                 continue;
             }
 
             skillLevel = profile.getSkillLevel(skill);
-            objective.getScore(server.getOfflinePlayer(SkillUtils.getSkillName(skill))).setScore(skillLevel);
+            objective.getScore(server.getOfflinePlayer(skill.getSkillName())).setScore(skillLevel);
             powerLevel += skillLevel;
         }
 
@@ -278,9 +277,9 @@ public class ScoreboardManager {
         int powerLevel = 0;
         int skillLevel;
 
-        for (SkillType skill : SkillType.nonChildSkills()) {
+        for (SkillType skill : SkillType.NON_CHILD_SKILLS) {
             skillLevel = targetProfile.getSkillLevel(skill);
-            objective.getScore(server.getOfflinePlayer(SkillUtils.getSkillName(skill))).setScore(skillLevel);
+            objective.getScore(server.getOfflinePlayer(skill.getSkillName())).setScore(skillLevel);
             powerLevel += skillLevel;
         }
 

+ 3 - 3
src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java

@@ -51,7 +51,7 @@ public final class CombatUtils {
         SwordsManager swordsManager = mcMMOPlayer.getSwordsManager();
 
         if (swordsManager.canActivateAbility()) {
-            SkillUtils.abilityCheck(mcMMOPlayer, SkillType.SWORDS);
+            mcMMOPlayer.checkAbilityActivation(SkillType.SWORDS);
         }
 
         if (swordsManager.canUseBleed()) {
@@ -73,7 +73,7 @@ public final class CombatUtils {
         AxesManager axesManager = mcMMOPlayer.getAxesManager();
 
         if (axesManager.canActivateAbility()) {
-            SkillUtils.abilityCheck(mcMMOPlayer, SkillType.AXES);
+            mcMMOPlayer.checkAbilityActivation(SkillType.AXES);
         }
 
         if (axesManager.canUseAxeMastery()) {
@@ -107,7 +107,7 @@ public final class CombatUtils {
         UnarmedManager unarmedManager = mcMMOPlayer.getUnarmedManager();
 
         if (unarmedManager.canActivateAbility()) {
-            SkillUtils.abilityCheck(mcMMOPlayer, SkillType.UNARMED);
+            mcMMOPlayer.checkAbilityActivation(SkillType.UNARMED);
         }
 
         if (unarmedManager.canUseIronArm()) {

+ 41 - 350
src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java

@@ -3,39 +3,24 @@ package com.gmail.nossr50.util.skills;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.bukkit.Location;
 import org.bukkit.Material;
-import org.bukkit.Sound;
-import org.bukkit.block.Block;
 import org.bukkit.enchantments.Enchantment;
 import org.bukkit.entity.Player;
 import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.PlayerInventory;
 import org.bukkit.inventory.meta.ItemMeta;
-import org.bukkit.plugin.PluginManager;
 import org.bukkit.potion.PotionEffect;
 import org.bukkit.potion.PotionEffectType;
 
-import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.config.HiddenConfig;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
-import com.gmail.nossr50.datatypes.player.PlayerProfile;
 import com.gmail.nossr50.datatypes.skills.AbilityType;
 import com.gmail.nossr50.datatypes.skills.SkillType;
-import com.gmail.nossr50.datatypes.skills.ToolType;
-import com.gmail.nossr50.events.experience.McMMOPlayerLevelUpEvent;
-import com.gmail.nossr50.events.fake.FakeBlockBreakEvent;
-import com.gmail.nossr50.events.fake.FakeBlockDamageEvent;
-import com.gmail.nossr50.events.fake.FakePlayerAnimationEvent;
-import com.gmail.nossr50.events.skills.abilities.McMMOPlayerAbilityActivateEvent;
 import com.gmail.nossr50.locale.LocaleLoader;
-import com.gmail.nossr50.runnables.skills.AbilityDisableTask;
-import com.gmail.nossr50.runnables.skills.ToolLowerTask;
 import com.gmail.nossr50.util.ItemUtils;
 import com.gmail.nossr50.util.Misc;
-import com.gmail.nossr50.util.ModUtils;
-import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.StringUtils;
 import com.gmail.nossr50.util.player.UserManager;
 
@@ -78,108 +63,7 @@ public class SkillUtils {
      * @return true if the cooldown is expired
      */
     public static boolean cooldownExpired(long deactivatedTimeStamp, int cooldown) {
-        return (System.currentTimeMillis() >= (deactivatedTimeStamp + cooldown) * Misc.TIME_CONVERSION_FACTOR);
-    }
-
-    /**
-     * Process activating abilities & readying the tool.
-     *
-     * @param player The player using the ability
-     * @param skill The skill the ability is tied to
-     */
-    public static void activationCheck(Player player, SkillType skill) {
-        if (Config.getInstance().getAbilitiesOnlyActivateWhenSneaking() && !player.isSneaking()) {
-            return;
-        }
-
-        ItemStack inHand = player.getItemInHand();
-
-        if (ModUtils.isCustomTool(inHand) && !ModUtils.getToolFromItemStack(inHand).isAbilityEnabled()) {
-            return;
-        }
-
-        McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
-
-        if (!mcMMOPlayer.getAbilityUse()) {
-            return;
-        }
-
-        for (AbilityType abilityType : AbilityType.values()) {
-            if (mcMMOPlayer.getAbilityMode(abilityType)) {
-                return;
-            }
-        }
-
-        PlayerProfile playerProfile = mcMMOPlayer.getProfile();
-        AbilityType ability = skill.getAbility();
-        ToolType tool = skill.getTool();
-
-        /*
-         * Woodcutting & Axes need to be treated differently.
-         * Basically the tool always needs to ready and we check to see if the cooldown is over when the user takes action
-         */
-        if (ability.getPermissions(player) && tool.inHand(inHand) && !mcMMOPlayer.getToolPreparationMode(tool)) {
-            if (skill != SkillType.WOODCUTTING && skill != SkillType.AXES) {
-                int timeRemaining = calculateTimeLeft(playerProfile.getSkillDATS(ability) * Misc.TIME_CONVERSION_FACTOR, ability.getCooldown(), player);
-
-                if (!mcMMOPlayer.getAbilityMode(ability) && timeRemaining > 0) {
-                    player.sendMessage(LocaleLoader.getString("Skills.TooTired", timeRemaining));
-                    return;
-                }
-            }
-
-            if (Config.getInstance().getAbilityMessagesEnabled()) {
-                player.sendMessage(tool.getRaiseTool());
-            }
-
-            mcMMOPlayer.setToolPreparationATS(tool, System.currentTimeMillis());
-            mcMMOPlayer.setToolPreparationMode(tool, true);
-            new ToolLowerTask(mcMMOPlayer, tool).runTaskLaterAsynchronously(mcMMO.p, 4 * Misc.TICK_CONVERSION_FACTOR);
-        }
-    }
-
-    /**
-     * Check the XP of a skill.
-     *
-     * @param skillType The skill to check
-     * @param player The player whose skill to check
-     * @param profile The profile of the player whose skill to check
-     */
-    public static void xpCheckSkill(SkillType skillType, Player player, PlayerProfile profile) {
-        int levelsGained = 0;
-        float xpRemoved = 0;
-
-        if (profile.getSkillXpLevelRaw(skillType) >= profile.getXpToLevel(skillType)) {
-            McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
-
-            while (profile.getSkillXpLevelRaw(skillType) >= profile.getXpToLevel(skillType)) {
-                if ((skillType.getMaxLevel() >= profile.getSkillLevel(skillType) + 1) && (Config.getInstance().getPowerLevelCap() >= mcMMOPlayer.getPowerLevel() + 1)) {
-                    int xp = profile.getXpToLevel(skillType);
-                    xpRemoved += xp;
-
-                    profile.removeXp(skillType, xp);
-                    levelsGained++;
-                    profile.skillUp(skillType, 1);
-                }
-                else {
-                    profile.addLevels(skillType, 0);
-                }
-            }
-
-            McMMOPlayerLevelUpEvent eventToFire = new McMMOPlayerLevelUpEvent(player, skillType, levelsGained);
-            mcMMO.p.getServer().getPluginManager().callEvent(eventToFire);
-
-            if (eventToFire.isCancelled()) {
-                profile.modifySkill(skillType, profile.getSkillLevel(skillType) - levelsGained);
-                profile.setSkillXpLevel(skillType, profile.getSkillXpLevelRaw(skillType) + xpRemoved);
-                return;
-            }
-
-            String capitalized = StringUtils.getCapitalized(skillType.toString());
-
-            player.playSound(player.getLocation(), Sound.LEVEL_UP, Misc.LEVELUP_VOLUME, Misc.LEVELUP_PITCH);
-            player.sendMessage(LocaleLoader.getString(capitalized + ".Skillup", levelsGained, profile.getSkillLevel(skillType)));
-        }
+        return System.currentTimeMillis() >= (deactivatedTimeStamp + cooldown) * Misc.TIME_CONVERSION_FACTOR;
     }
 
     /**
@@ -189,174 +73,14 @@ public class SkillUtils {
      * @return true if this is a valid skill, false otherwise
      */
     public static boolean isSkill(String skillName) {
-        if (!Config.getInstance().getLocale().equalsIgnoreCase("en_US")) {
-            return isLocalizedSkill(skillName);
-        }
-
-        return SkillType.getSkill(skillName) != null;
-    }
-
-    private static boolean isLocalizedSkill(String skillName) {
-        for (SkillType skill : SkillType.values()) {
-            if (skillName.equalsIgnoreCase(LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".SkillName"))) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public static String getSkillName(SkillType skill) {
-        if (!Config.getInstance().getLocale().equalsIgnoreCase("en_US")) {
-            return StringUtils.getCapitalized(LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".SkillName"));
-        }
-
-        return StringUtils.getCapitalized(skill.toString());
-    }
-
-    /**
-     * Check if the player has any combat skill permissions.
-     *
-     * @param player The player to check permissions for
-     * @return true if the player has combat skills, false otherwise
-     */
-    public static boolean hasCombatSkills(Player player) {
-        return Permissions.skillEnabled(player, SkillType.AXES)
-                || Permissions.skillEnabled(player, SkillType.ARCHERY)
-                || Permissions.skillEnabled(player, SkillType.SWORDS)
-                || Permissions.skillEnabled(player, SkillType.TAMING)
-                || Permissions.skillEnabled(player, SkillType.UNARMED);
-    }
-
-    /**
-     * Check if the player has any gathering skill permissions.
-     *
-     * @param player The player to check permissions for
-     * @return true if the player has gathering skills, false otherwise
-     */
-    public static boolean hasGatheringSkills(Player player) {
-        return Permissions.skillEnabled(player, SkillType.EXCAVATION)
-                || Permissions.skillEnabled(player, SkillType.FISHING)
-                || Permissions.skillEnabled(player, SkillType.HERBALISM)
-                || Permissions.skillEnabled(player, SkillType.MINING)
-                || Permissions.skillEnabled(player, SkillType.WOODCUTTING);
-    }
-
-    /**
-     * Check if the player has any misc skill permissions.
-     *
-     * @param player The player to check permissions for
-     * @return true if the player has misc skills, false otherwise
-     */
-    public static boolean hasMiscSkills(Player player) {
-        return Permissions.skillEnabled(player, SkillType.ACROBATICS)
-                || Permissions.skillEnabled(player, SkillType.SMELTING)
-                || Permissions.skillEnabled(player, SkillType.REPAIR);
-    }
-
-    /**
-     * Check to see if an ability can be activated.
-     *
-     * @param mcMMOPlayer The player activating the ability
-     * @param type The skill the ability is based on
-     */
-    public static void abilityCheck(McMMOPlayer mcMMOPlayer, SkillType type) {
-        ToolType tool = type.getTool();
-        AbilityType ability = type.getAbility();
-
-        mcMMOPlayer.setToolPreparationMode(tool, false);
-
-        Player player = mcMMOPlayer.getPlayer();
-        PlayerProfile playerProfile = mcMMOPlayer.getProfile();
-
-        int timeRemaining = calculateTimeLeft(playerProfile.getSkillDATS(ability) * Misc.TIME_CONVERSION_FACTOR, ability.getCooldown(), player);
-
-        /*
-         * Axes and Woodcutting are odd because they share the same tool.
-         * We show them the too tired message when they take action.
-         */
-        if (type == SkillType.WOODCUTTING || type == SkillType.AXES) {
-            if (!mcMMOPlayer.getAbilityMode(ability) && timeRemaining > 0) {
-                player.sendMessage(LocaleLoader.getString("Skills.TooTired", timeRemaining));
-                return;
-            }
-        }
-
-        if (!mcMMOPlayer.getAbilityMode(ability) && timeRemaining <= 0) {
-            McMMOPlayerAbilityActivateEvent event = new McMMOPlayerAbilityActivateEvent(player, type);
-            mcMMO.p.getServer().getPluginManager().callEvent(event);
-
-            if (event.isCancelled()) {
-                return;
-            }
-
-            int ticks = PerksUtils.handleActivationPerks(player, 2 + (playerProfile.getSkillLevel(type) / AdvancedConfig.getInstance().getAbilityLength()), ability.getMaxLength());
-
-            ParticleEffectUtils.playAbilityEnabledEffect(player);
-
-            if (mcMMOPlayer.useChatNotifications()) {
-                player.sendMessage(ability.getAbilityOn());
-            }
-
-            SkillUtils.sendSkillMessage(player, ability.getAbilityPlayer(player));
-
-            playerProfile.setSkillDATS(ability, System.currentTimeMillis() + (ticks * Misc.TIME_CONVERSION_FACTOR));
-            mcMMOPlayer.setAbilityMode(ability, true);
-
-            if (ability == AbilityType.SUPER_BREAKER || ability == AbilityType.GIGA_DRILL_BREAKER) {
-                handleAbilitySpeedIncrease(player);
-            }
-
-            new AbilityDisableTask(mcMMOPlayer, ability).runTaskLater(mcMMO.p, ticks * Misc.TICK_CONVERSION_FACTOR);
-        }
-    }
-
-    /**
-     * Check to see if ability should be triggered.
-     *
-     * @param player The player using the ability
-     * @param block The block modified by the ability
-     * @param ability The ability to check
-     * @return true if the ability should activate, false otherwise
-     */
-    public static boolean triggerCheck(Player player, Block block, AbilityType ability) {
-        boolean activate = true;
-
-        switch (ability) {
-            case BERSERK:
-            case BLOCK_CRACKER:
-            case LEAF_BLOWER:
-                if (!ability.blockCheck(block.getState())) {
-                    activate = false;
-                    break;
-                }
-
-                if (!blockBreakSimulate(block, player, true)) {
-                    activate = false;
-                    break;
-                }
-                break;
-
-            case GIGA_DRILL_BREAKER:
-            case SUPER_BREAKER:
-            case GREEN_TERRA:
-                if (!ability.blockCheck(block.getState())) {
-                    activate = false;
-                    break;
-                }
-                break;
-
-            default:
-                activate = false;
-                break;
-        }
-
-        return activate;
+        return Config.getInstance().getLocale().equalsIgnoreCase("en_US") ? SkillType.getSkill(skillName) != null : isLocalizedSkill(skillName);
     }
 
     public static void sendSkillMessage(Player player, String message) {
+        Location location = player.getLocation();
+
         for (Player otherPlayer : player.getWorld().getPlayers()) {
-            if (otherPlayer != player && Misc.isNear(player.getLocation(), otherPlayer.getLocation(), Misc.SKILL_MESSAGE_MAX_SENDING_DISTANCE)) {
+            if (otherPlayer != player && Misc.isNear(location, otherPlayer.getLocation(), Misc.SKILL_MESSAGE_MAX_SENDING_DISTANCE)) {
                 otherPlayer.sendMessage(message);
             }
         }
@@ -408,48 +132,39 @@ public class SkillUtils {
     }
 
     public static void handleAbilitySpeedDecrease(Player player) {
-        if (HiddenConfig.getInstance().useEnchantmentBuffs()) {
-            PlayerInventory playerInventory = player.getInventory();
-
-            for (int i = 0; i < playerInventory.getContents().length; i++) {
-                ItemStack item = playerInventory.getItem(i);
-                playerInventory.setItem(i, removeAbilityBuff(item));
-            }
+        if (!HiddenConfig.getInstance().useEnchantmentBuffs()) {
+            return;
         }
-    }
 
-    public static ItemStack removeAbilityBuff(ItemStack item) {
-        if (item == null || item.getType() == Material.AIR) {
-            return item;
+        for (ItemStack item : player.getInventory().getContents()) {
+            removeAbilityBuff(item);
         }
+    }
 
-        if (!ItemUtils.isPickaxe(item) && !ItemUtils.isShovel(item)) {
-            return item;
+    public static void removeAbilityBuff(ItemStack item) {
+        if (item == null || item.getType() == Material.AIR || (!ItemUtils.isPickaxe(item) && !ItemUtils.isShovel(item)) || !item.containsEnchantment(Enchantment.DIG_SPEED)) {
+            return;
         }
 
-        if (item.containsEnchantment(Enchantment.DIG_SPEED)) {
-            ItemMeta itemMeta = item.getItemMeta();
+        ItemMeta itemMeta = item.getItemMeta();
 
-            if (itemMeta.hasLore()) {
-                List<String> itemLore = itemMeta.getLore();
+        if (itemMeta.hasLore()) {
+            List<String> itemLore = itemMeta.getLore();
 
-                if (itemLore.remove("mcMMO Ability Tool")) {
-                    int efficiencyLevel = item.getEnchantmentLevel(Enchantment.DIG_SPEED);
+            if (itemLore.remove("mcMMO Ability Tool")) {
+                int efficiencyLevel = item.getEnchantmentLevel(Enchantment.DIG_SPEED);
 
-                    if (efficiencyLevel <= AdvancedConfig.getInstance().getEnchantBuff()) {
-                        itemMeta.removeEnchant(Enchantment.DIG_SPEED);
-                    }
-                    else {
-                        itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel - AdvancedConfig.getInstance().getEnchantBuff(), true);
-                    }
-
-                    itemMeta.setLore(itemLore);
-                    item.setItemMeta(itemMeta);
+                if (efficiencyLevel <= AdvancedConfig.getInstance().getEnchantBuff()) {
+                    itemMeta.removeEnchant(Enchantment.DIG_SPEED);
+                }
+                else {
+                    itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel - AdvancedConfig.getInstance().getEnchantBuff(), true);
                 }
+
+                itemMeta.setLore(itemLore);
+                item.setItemMeta(itemMeta);
             }
         }
-
-        return item;
     }
 
     /**
@@ -458,53 +173,29 @@ public class SkillUtils {
      * @param itemStack The ItemStack which durability should be modified
      * @return the itemStack with modified durability
      */
-    public static ItemStack handleDurabilityChange(ItemStack itemStack, int durabilityModifier) {
-        short finalDurability = (short) (itemStack.getDurability() + durabilityModifier);
-        short maxDurability = itemStack.getType().getMaxDurability();
-        boolean overMax = (finalDurability >= maxDurability);
-
-        itemStack.setDurability(overMax ? maxDurability : finalDurability);
-        return itemStack;
-    }
-
-    /**
-     * Simulate a block break event.
-     *
-     * @param block The block to break
-     * @param player The player breaking the block
-     * @param shouldArmSwing true if an armswing event should be fired, false otherwise
-     * @return true if the event wasn't cancelled, false otherwise
-     */
-    public static boolean blockBreakSimulate(Block block, Player player, boolean shouldArmSwing) {
-        PluginManager pluginManger = mcMMO.p.getServer().getPluginManager();
-
-        // Support for NoCheat
-        if (shouldArmSwing) {
-            pluginManger.callEvent(new FakePlayerAnimationEvent(player));
-        }
-
-        FakeBlockDamageEvent damageEvent = new FakeBlockDamageEvent(player, block, player.getItemInHand(), true);
-        pluginManger.callEvent(damageEvent);
-
-        FakeBlockBreakEvent breakEvent = new FakeBlockBreakEvent(block, player);
-        pluginManger.callEvent(breakEvent);
-
-        return !damageEvent.isCancelled() && !breakEvent.isCancelled();
+    public static void handleDurabilityChange(ItemStack itemStack, int durabilityModifier) {
+        itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, itemStack.getType().getMaxDurability()));
     }
 
     public static boolean activationSuccessful(Player player, SkillType skill, double maxChance, int maxLevel) {
-        int skillLevel = UserManager.getPlayer(player).getProfile().getSkillLevel(skill);
-        int activationChance = PerksUtils.handleLuckyPerks(player, skill);
-        double chance = (maxChance / maxLevel) * Math.min(skillLevel, maxLevel);
-
-        return chance > Misc.getRandom().nextInt(activationChance);
+        return activationSuccessful(UserManager.getPlayer(player).getProfile().getSkillLevel(skill), PerksUtils.handleLuckyPerks(player, skill), maxChance, maxLevel);
     }
 
     public static boolean activationSuccessful(int skillLevel, int activationChance, double maxChance, int maxLevel) {
-        return ((maxChance / maxLevel) * Math.min(skillLevel, maxLevel)) > Misc.getRandom().nextInt(activationChance);
+        return (maxChance / maxLevel) * Math.min(skillLevel, maxLevel) > Misc.getRandom().nextInt(activationChance);
     }
 
     public static boolean treasureDropSuccessful(double dropChance, int activationChance) {
         return dropChance > Misc.getRandom().nextDouble() * activationChance;
     }
+
+    private static boolean isLocalizedSkill(String skillName) {
+        for (SkillType skill : SkillType.values()) {
+            if (skillName.equalsIgnoreCase(LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".SkillName"))) {
+                return true;
+            }
+        }
+
+        return false;
+    }
 }

+ 1 - 0
src/main/resources/locale/locale_en_US.properties

@@ -757,6 +757,7 @@ Skills.Header=[[RED]]-----[][[GREEN]]{0}[[RED]][]-----
 Skills.NeedMore=[[DARK_RED]]You need more [[GRAY]]{0}
 Skills.Parents = PARENTS
 Skills.Stats=[[YELLOW]]{0}[[GREEN]]{1}[[DARK_AQUA]] XP([[GRAY]]{2}[[DARK_AQUA]]/[[GRAY]]{3}[[DARK_AQUA]])
+Skills.ChildStats=[[YELLOW]]{0}[[GREEN]]{1}
 Skills.TooTired=[[RED]]You are too tired to use that ability again. [[YELLOW]]({0}s)
 Skills.Cancelled=[[RED]]{0} cancelled!
 Skills.ConfirmOrCancel=[[GREEN]]Right-click again to confirm [[GOLD]]{0}[[GREEN]]. Left-click to cancel.