瀏覽代碼

Straightening up our Managers more, also fixed a few bugs regarding
unlock levels and Deflect not working properly.

GJ 12 年之前
父節點
當前提交
0c027ca697

+ 2 - 0
Changelog.txt

@@ -9,6 +9,8 @@ Key:
 
 Version 1.4.02-dev
  + Added API to get the skill and power level caps.
+ = Fixed bug where Deflect was calculated based on the attacker, not the defender
+ = Fixed bug where some skills weren't registering as unlocked until one level later
 
 Version 1.4.01
  = Fixed bug where trying to use /mctop or /xplock with the Smelting child skill caused NPEs

+ 7 - 6
src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java

@@ -69,10 +69,11 @@ public class McMMOPlayer {
     private boolean placedSalvageAnvil;
     private boolean godMode;
 
-    private Map<AbilityType, Boolean> abilityMode = new HashMap<AbilityType, Boolean>();
+    private Map<AbilityType, Boolean> abilityMode     = new HashMap<AbilityType, Boolean>();
     private Map<AbilityType, Boolean> abilityInformed = new HashMap<AbilityType, Boolean>();
-    private Map<ToolType, Boolean> toolPreparationMode = new HashMap<ToolType, Boolean>();
-    private Map<ToolType, Integer> toolATS = new HashMap<ToolType, Integer>();
+
+    private Map<ToolType, Boolean> toolMode = new HashMap<ToolType, Boolean>();
+    private Map<ToolType, Integer> toolATS  = new HashMap<ToolType, Integer>();
 
     private int recentlyHurt;
     private int respawnATS;
@@ -110,7 +111,7 @@ public class McMMOPlayer {
         }
 
         for (ToolType toolType : ToolType.values()) {
-            toolPreparationMode.put(toolType, false);
+            toolMode.put(toolType, false);
             toolATS.put(toolType, 0);
         }
     }
@@ -219,7 +220,7 @@ public class McMMOPlayer {
      * @return true if the tool is prepped, false otherwise
      */
     public boolean getToolPreparationMode(ToolType tool) {
-        return toolPreparationMode.get(tool);
+        return toolMode.get(tool);
     }
 
     public boolean getAbilityUse() {
@@ -250,7 +251,7 @@ public class McMMOPlayer {
      * @param bool true if the tool should be prepped, false otherwise
      */
     public void setToolPreparationMode(ToolType tool, boolean bool) {
-        toolPreparationMode.put(tool, bool);
+        toolMode.put(tool, bool);
     }
 
     /**

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

@@ -7,6 +7,7 @@ import org.bukkit.Sound;
 import org.bukkit.block.Block;
 import org.bukkit.block.BlockFace;
 import org.bukkit.block.BlockState;
+import org.bukkit.enchantments.Enchantment;
 import org.bukkit.entity.Player;
 import org.bukkit.event.EventHandler;
 import org.bukkit.event.EventPriority;
@@ -234,20 +235,26 @@ public class BlockListener implements Listener {
         }
 
         BlockState blockState = event.getBlock().getState();
-        McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
-        HerbalismManager herbalismManager = mcMMOPlayer.getHerbalismManager();
-        SmeltingManager smeltingManager = mcMMOPlayer.getSmeltingManager();
+        ItemStack heldItem = player.getItemInHand();
 
-        if (herbalismManager.canUseHylianLuck()) {
-            if (herbalismManager.processHylianLuck(blockState)) {
-                blockState.update(true);
-                event.setCancelled(true);
+        if (ItemUtils.isSword(heldItem)) {
+            HerbalismManager herbalismManager = UserManager.getPlayer(player).getHerbalismManager();
+
+            if (herbalismManager.canUseHylianLuck()) {
+                if (herbalismManager.processHylianLuck(blockState)) {
+                    blockState.update(true);
+                    event.setCancelled(true);
+                }
             }
         }
-        else if (smeltingManager.canUseFluxMining(blockState)) {
-            if (smeltingManager.processFluxMining(blockState)) {
-                blockState.update(true);
-                event.setCancelled(true);
+        else if (ItemUtils.isPickaxe(heldItem) && !heldItem.containsEnchantment(Enchantment.SILK_TOUCH)) {
+            SmeltingManager smeltingManager = UserManager.getPlayer(player).getSmeltingManager();
+
+            if (smeltingManager.canUseFluxMining(blockState)) {
+                if (smeltingManager.processFluxMining(blockState)) {
+                    blockState.update(true);
+                    event.setCancelled(true);
+                }
             }
         }
     }

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

@@ -115,8 +115,8 @@ public class EntityListener implements Listener {
             Player defendingPlayer = (Player) defender;
             Player attackingPlayer = (Player) attacker;
 
-            // TODO: Why?
-            if (defendingPlayer == attackingPlayer) {
+            // We want to make sure we're not gaining XP or applying abilities when we hit ourselves
+            if (defendingPlayer.equals(attackingPlayer)) {
                 return;
             }
 

+ 6 - 6
src/main/java/com/gmail/nossr50/skills/acrobatics/AcrobaticsManager.java

@@ -11,6 +11,7 @@ import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.SkillManager;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
+import com.gmail.nossr50.util.skills.CombatUtils;
 import com.gmail.nossr50.util.skills.ParticleEffectUtils;
 import com.gmail.nossr50.util.skills.SkillUtils;
 
@@ -27,12 +28,11 @@ public class AcrobaticsManager extends SkillManager {
 
     public boolean canDodge(Entity damager) {
         if (Permissions.dodge(getPlayer())) {
-            if (damager instanceof Player && SkillType.ACROBATICS.getPVPEnabled()) {
-                return true;
-            }
-            else if (!(damager instanceof Player) && SkillType.ACROBATICS.getPVEEnabled() && !(damager instanceof LightningStrike && Acrobatics.dodgeLightningDisabled)) {
-                return true;
+            if (damager instanceof LightningStrike && Acrobatics.dodgeLightningDisabled) {
+                return false;
             }
+
+            return CombatUtils.shouldProcessSkill(damager, skill);
         }
 
         return false;
@@ -48,7 +48,7 @@ public class AcrobaticsManager extends SkillManager {
         int modifiedDamage = Acrobatics.calculateModifiedDodgeDamage(damage, Acrobatics.dodgeDamageModifier);
         Player player = getPlayer();
 
-        if (!isFatal(modifiedDamage) && SkillUtils.activationSuccessful(player, skill, Acrobatics.dodgeMaxChance, Acrobatics.dodgeMaxBonusLevel)) {
+        if (!isFatal(modifiedDamage) && SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Acrobatics.dodgeMaxChance, Acrobatics.dodgeMaxBonusLevel)) {
             ParticleEffectUtils.playDodgeEffect(player);
 
             if (mcMMOPlayer.useChatNotifications()) {

+ 5 - 9
src/main/java/com/gmail/nossr50/skills/archery/ArcheryManager.java

@@ -26,9 +26,7 @@ public class ArcheryManager extends SkillManager {
     }
 
     public boolean canSkillShot() {
-        Player player = getPlayer();
-
-        return SkillUtils.unlockLevelReached(player, skill, Archery.skillShotIncreaseLevel) && Permissions.bonusDamage(player, skill);
+        return getSkillLevel() >= Archery.skillShotIncreaseLevel && Permissions.bonusDamage(getPlayer(), skill);
     }
 
     public boolean canTrackArrows() {
@@ -64,7 +62,7 @@ public class ArcheryManager extends SkillManager {
      * @param target The {@link LivingEntity} damaged by the arrow
      */
     public void trackArrows(LivingEntity target) {
-        if (SkillUtils.activationSuccessful(getPlayer(), skill, Archery.retrieveMaxChance, Archery.retrieveMaxBonusLevel)) {
+        if (SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Archery.retrieveMaxChance, Archery.retrieveMaxBonusLevel)) {
             Archery.incrementTrackerValue(target);
         }
     }
@@ -72,14 +70,12 @@ public class ArcheryManager extends SkillManager {
     /**
      * Handle the effects of the Daze ability
      *
-     * @param defender The player being affected by the ability
+     * @param defender The {@link Player} being affected by the ability
      * @param damage The amount of damage initially dealt by the event
      * @return the modified event damage if the ability was successful, the original event damage otherwise
      */
     public int dazeCheck(Player defender, int damage) {
-        Player attacker = getPlayer();
-
-        if (SkillUtils.activationSuccessful(attacker, skill, Archery.dazeMaxBonus, Archery.dazeMaxBonusLevel)) {
+        if (SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Archery.dazeMaxBonus, Archery.dazeMaxBonusLevel)) {
             Location dazedLocation = defender.getLocation();
             dazedLocation.setPitch(90 - Misc.getRandom().nextInt(181));
 
@@ -91,7 +87,7 @@ public class ArcheryManager extends SkillManager {
             }
 
             if (mcMMOPlayer.useChatNotifications()) {
-                attacker.sendMessage(LocaleLoader.getString("Combat.TargetDazed"));
+                getPlayer().sendMessage(LocaleLoader.getString("Combat.TargetDazed"));
             }
 
             return damage + Archery.dazeModifier;

+ 7 - 8
src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java

@@ -68,10 +68,8 @@ public class AxesManager extends SkillManager {
      * @return the modified event damage if the ability was successful, the original event damage otherwise
      */
     public int criticalHitCheck(LivingEntity target, int damage) {
-        Player player = getPlayer();
-
-        if (SkillUtils.activationSuccessful(player, skill, Axes.criticalHitMaxChance, Axes.criticalHitMaxBonusLevel)) {
-            player.sendMessage(LocaleLoader.getString("Axes.Combat.CriticalHit"));
+        if (SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Axes.criticalHitMaxChance, Axes.criticalHitMaxBonusLevel)) {
+            getPlayer().sendMessage(LocaleLoader.getString("Axes.Combat.CriticalHit"));
 
             if (target instanceof Player) {
                 ((Player) target).sendMessage(LocaleLoader.getString("Axes.Combat.CritStruck"));
@@ -94,10 +92,11 @@ public class AxesManager extends SkillManager {
         int durabilityDamage = 1 + (getSkillLevel() / Axes.impactIncreaseLevel);
 
         for (ItemStack armor : target.getEquipment().getArmorContents()) {
-            if (ItemUtils.isArmor(armor) && SkillUtils.activationSuccessful(getPlayer(), skill, Axes.impactChance)) {
+            if (ItemUtils.isArmor(armor) && Axes.impactChance > getActivationChance()) {
                 double durabilityModifier = 1 / (armor.getEnchantmentLevel(Enchantment.DURABILITY) + 1); // Modifier to simulate the durability enchantment behavior
                 double modifiedDurabilityDamage = durabilityDamage * durabilityModifier;
-                double maxDurabilityDamage = (ModUtils.isCustomArmor(armor) ? ModUtils.getArmorFromItemStack(armor).getDurability() : armor.getType().getMaxDurability()) * Axes.impactMaxDurabilityModifier;
+                short maxDurability = ModUtils.isCustomArmor(armor) ? ModUtils.getArmorFromItemStack(armor).getDurability() : armor.getType().getMaxDurability();
+                double maxDurabilityDamage = maxDurability * Axes.impactMaxDurabilityModifier;
 
                 armor.setDurability((short) (Math.min(modifiedDurabilityDamage, maxDurabilityDamage) + armor.getDurability()));
             }
@@ -112,9 +111,9 @@ public class AxesManager extends SkillManager {
      * @return the modified event damage if the ability was successful, the original event damage otherwise
      */
     public int greaterImpactCheck(LivingEntity target, int damage) {
-        Player player = getPlayer();
+        if (Axes.greaterImpactChance > getActivationChance()) {
+            Player player = getPlayer();
 
-        if (SkillUtils.activationSuccessful(player, skill, Axes.greaterImpactChance)) {
             ParticleEffectUtils.playGreaterImpactEffect(target);
             target.setVelocity(player.getLocation().getDirection().normalize().multiply(Axes.greaterImpactKnockbackMultiplier));
 

+ 2 - 4
src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java

@@ -38,9 +38,7 @@ public class FishingManager extends SkillManager {
     }
 
     public boolean canShake(Entity target) {
-        Player player = getPlayer();
-
-        return target instanceof LivingEntity && SkillUtils.unlockLevelReached(player, skill, AdvancedConfig.getInstance().getShakeUnlockLevel()) && Permissions.shake(player);
+        return target instanceof LivingEntity && getSkillLevel() >= AdvancedConfig.getInstance().getShakeUnlockLevel() && Permissions.shake(getPlayer());
     }
 
     /**
@@ -136,7 +134,7 @@ public class FishingManager extends SkillManager {
      * @param mob The {@link LivingEntity} affected by the ability
      */
     public void shakeCheck(LivingEntity target) {
-        if (SkillUtils.activationSuccessful(getPlayer(), skill, getShakeProbability())) {
+        if (getActivationChance() > getShakeProbability()) {
             Map<ItemStack, Integer> possibleDrops = new HashMap<ItemStack, Integer>();
 
             Fishing.findPossibleDrops(target, possibleDrops);

+ 8 - 15
src/main/java/com/gmail/nossr50/skills/herbalism/HerbalismManager.java

@@ -24,7 +24,6 @@ import com.gmail.nossr50.runnables.skills.herbalism.GreenTerraTimerTask;
 import com.gmail.nossr50.runnables.skills.herbalism.GreenThumbTimerTask;
 import com.gmail.nossr50.skills.SkillManager;
 import com.gmail.nossr50.util.BlockUtils;
-import com.gmail.nossr50.util.ItemUtils;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.ModUtils;
 import com.gmail.nossr50.util.Permissions;
@@ -54,9 +53,7 @@ public class HerbalismManager extends SkillManager {
     }
 
     public boolean canUseHylianLuck() {
-        Player player = getPlayer();
-
-        return ItemUtils.isSword(player.getItemInHand()) && Permissions.hylianLuck(player);
+        return Permissions.hylianLuck(getPlayer());
     }
 
     public boolean canGreenTerraBlock(BlockState blockState) {
@@ -150,7 +147,7 @@ public class HerbalismManager extends SkillManager {
             xp = customBlock.getXpGain();
         }
 
-        if (Permissions.doubleDrops(player, skill) && SkillUtils.activationSuccessful(player, skill, Herbalism.doubleDropsMaxChance, Herbalism.doubleDropsMaxLevel)) {
+        if (Permissions.doubleDrops(player, skill) && SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Herbalism.doubleDropsMaxChance, Herbalism.doubleDropsMaxLevel)) {
             Location location = blockState.getLocation();
 
             if (dropItem != null && herbalismBlock != null && herbalismBlock.canDoubleDrop()) {
@@ -178,10 +175,8 @@ public class HerbalismManager extends SkillManager {
      * @return true if the ability was successful, false otherwise
      */
     public boolean processGreenThumbBlocks(BlockState blockState) {
-        Player player = getPlayer();
-
-        if (!SkillUtils.activationSuccessful(player, skill, Herbalism.greenThumbMaxChance, Herbalism.greenThumbMaxLevel)) {
-            player.sendMessage(LocaleLoader.getString("Herbalism.Ability.GTh.Fail"));
+        if (!SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Herbalism.greenThumbMaxChance, Herbalism.greenThumbMaxLevel)) {
+            getPlayer().sendMessage(LocaleLoader.getString("Herbalism.Ability.GTh.Fail"));
             return false;
         }
 
@@ -195,9 +190,7 @@ public class HerbalismManager extends SkillManager {
      * @return true if the ability was successful, false otherwise
      */
     public boolean processHylianLuck(BlockState blockState) {
-        Player player = getPlayer();
-
-        if (!SkillUtils.activationSuccessful(player, skill, Herbalism.hylianLuckMaxChance, Herbalism.hylianLuckMaxLevel)) {
+        if (!SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Herbalism.hylianLuckMaxChance, Herbalism.hylianLuckMaxLevel)) {
             return false;
         }
 
@@ -236,7 +229,7 @@ public class HerbalismManager extends SkillManager {
         blockState.setType(Material.AIR);
 
         Misc.dropItem(blockState.getLocation(), treasures.get(Misc.getRandom().nextInt(treasures.size())).getDrop());
-        player.sendMessage(LocaleLoader.getString("Herbalism.HylianLuck"));
+        getPlayer().sendMessage(LocaleLoader.getString("Herbalism.HylianLuck"));
         return true;
     }
 
@@ -264,7 +257,7 @@ public class HerbalismManager extends SkillManager {
         playerInventory.removeItem(new ItemStack(Material.RED_MUSHROOM));
         player.updateInventory();
 
-        if (!SkillUtils.activationSuccessful(player, skill, Herbalism.shroomThumbMaxChance, Herbalism.shroomThumbMaxLevel)) {
+        if (!SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Herbalism.shroomThumbMaxChance, Herbalism.shroomThumbMaxLevel)) {
             player.sendMessage(LocaleLoader.getString("Herbalism.Ability.ShroomThumb.Fail"));
             return false;
         }
@@ -293,7 +286,7 @@ public class HerbalismManager extends SkillManager {
             mcMMO.p.getServer().getScheduler().scheduleSyncDelayedTask(mcMMO.p, new GreenTerraTimerTask(blockState), 0);
             return;
         }
-        else if (SkillUtils.activationSuccessful(player, skill, Herbalism.greenThumbMaxChance, Herbalism.greenThumbMaxLevel)) {
+        else if (SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Herbalism.greenThumbMaxChance, Herbalism.greenThumbMaxLevel)) {
             playerInventory.removeItem(seed);
             player.updateInventory(); // Needed until replacement available
 

+ 5 - 10
src/main/java/com/gmail/nossr50/skills/mining/MiningManager.java

@@ -30,38 +30,33 @@ public class MiningManager extends SkillManager{
     }
 
     public boolean canUseDemolitionsExpertise() {
-        Player player = getPlayer();
-
-        return SkillUtils.unlockLevelReached(player, skill, BlastMining.Tier.FOUR.getLevel()) && Permissions.demolitionsExpertise(player);
+        return getSkillLevel() >= BlastMining.Tier.FOUR.getLevel() && Permissions.demolitionsExpertise(getPlayer());
     }
 
     public boolean canDetonate() {
         Player player = getPlayer();
 
-        return player.isSneaking() && player.getItemInHand().getTypeId() == BlastMining.detonatorID && Permissions.remoteDetonation(player) && SkillUtils.unlockLevelReached(player, skill, BlastMining.Tier.ONE.getLevel());
+        return canUseBlastMining() && player.isSneaking() && player.getItemInHand().getTypeId() == BlastMining.detonatorID && Permissions.remoteDetonation(player);
     }
 
     public boolean canUseBlastMining() {
-        return SkillUtils.unlockLevelReached(getPlayer(), skill, BlastMining.Tier.ONE.getLevel());
+        return getSkillLevel() >= BlastMining.Tier.ONE.getLevel();
     }
 
     public boolean canUseBiggerBombs() {
-        Player player = getPlayer();
-
-        return Permissions.biggerBombs(player) && SkillUtils.unlockLevelReached(getPlayer(), skill, BlastMining.Tier.TWO.getLevel());
+        return getSkillLevel() >= BlastMining.Tier.TWO.getLevel() && Permissions.biggerBombs(getPlayer());
     }
 
     /**
      * Process double drops & XP gain for Mining.
      *
      * @param blockState The {@link BlockState} to check ability activation for
-     * @param player The {@link Player} using this ability
      */
     public void miningBlockCheck(BlockState blockState) {
         Player player = getPlayer();
         int xp = Mining.getBlockXp(blockState);
 
-        if (Permissions.doubleDrops(player, skill) && SkillUtils.activationSuccessful(player, skill, Mining.doubleDropsMaxChance, Mining.doubleDropsMaxLevel)) {
+        if (Permissions.doubleDrops(player, skill) && SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Mining.doubleDropsMaxChance, Mining.doubleDropsMaxLevel)) {
             if (player.getItemInHand().containsEnchantment(Enchantment.SILK_TOUCH)) {
                 Mining.handleSilkTouchDrops(blockState);
             }

+ 5 - 12
src/main/java/com/gmail/nossr50/skills/smelting/SmeltingManager.java

@@ -3,7 +3,6 @@ package com.gmail.nossr50.skills.smelting;
 import org.bukkit.Location;
 import org.bukkit.Material;
 import org.bukkit.block.BlockState;
-import org.bukkit.enchantments.Enchantment;
 import org.bukkit.entity.Player;
 import org.bukkit.event.inventory.FurnaceBurnEvent;
 import org.bukkit.inventory.ItemStack;
@@ -16,7 +15,6 @@ import com.gmail.nossr50.skills.SkillManager;
 import com.gmail.nossr50.skills.mining.Mining;
 import com.gmail.nossr50.skills.smelting.Smelting.Tier;
 import com.gmail.nossr50.util.BlockUtils;
-import com.gmail.nossr50.util.ItemUtils;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.skills.SkillUtils;
@@ -27,16 +25,11 @@ public class SmeltingManager extends SkillManager {
     }
 
     public boolean canUseFluxMining(BlockState blockState) {
-        Player player = getPlayer();
-        ItemStack heldItem = player.getItemInHand();
-
-        return BlockUtils.affectedByFluxMining(blockState) && ItemUtils.isPickaxe(heldItem) && !heldItem.containsEnchantment(Enchantment.SILK_TOUCH) && Permissions.fluxMining(player) && !mcMMO.placeStore.isTrue(blockState);
+        return getSkillLevel() >= Smelting.fluxMiningUnlockLevel && BlockUtils.affectedByFluxMining(blockState) && Permissions.fluxMining(getPlayer()) && !mcMMO.placeStore.isTrue(blockState);
     }
 
     public boolean canUseVanillaXpBoost() {
-        Player player = getPlayer();
-
-        return SkillUtils.unlockLevelReached(player, skill, Smelting.Tier.ONE.getLevel()) && Permissions.vanillaXpBoost(player, skill);
+        return getSkillLevel() >= Smelting.Tier.ONE.getLevel() && Permissions.vanillaXpBoost(getPlayer(), skill);
     }
 
     /**
@@ -48,7 +41,7 @@ public class SmeltingManager extends SkillManager {
     public boolean processFluxMining(BlockState blockState) {
         Player player = getPlayer();
 
-        if (SkillUtils.unlockLevelReached(player, skill, Smelting.fluxMiningUnlockLevel) && SkillUtils.activationSuccessful(player, skill, Smelting.fluxMiningChance)) {
+        if (getActivationChance() > Smelting.fluxMiningChance) {
             ItemStack item = null;
 
             switch (blockState.getType()) {
@@ -72,7 +65,7 @@ public class SmeltingManager extends SkillManager {
 
             Misc.dropItem(location, item);
 
-            if (Permissions.doubleDrops(player, skill) && SkillUtils.activationSuccessful(player, skill, Mining.doubleDropsMaxChance, Mining.doubleDropsMaxLevel)) {
+            if (Permissions.doubleDrops(player, skill) && SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Mining.doubleDropsMaxChance, Mining.doubleDropsMaxLevel)) {
                 Misc.dropItem(location, item);
             }
 
@@ -101,7 +94,7 @@ public class SmeltingManager extends SkillManager {
 
         applyXpGain(Smelting.getResourceXp(resourceType));
 
-        if (Permissions.doubleDrops(player, skill) && SkillUtils.activationSuccessful(player, skill, Smelting.secondSmeltMaxChance, Smelting.secondSmeltMaxLevel)) {
+        if (Permissions.doubleDrops(player, skill) && SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Smelting.secondSmeltMaxChance, Smelting.secondSmeltMaxLevel)) {
             ItemStack newResult = new ItemStack(result.getType(), result.getAmount() + 1);
             return newResult;
         }

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

@@ -28,6 +28,10 @@ public class SwordsManager extends SkillManager {
         return Permissions.bleed(getPlayer());
     }
 
+    public boolean canUseCounterAttack() {
+        return Permissions.counterAttack(getPlayer());
+    }
+
     public boolean canUseSerratedStrike() {
         return mcMMOPlayer.getAbilityMode(AbilityType.SERRATED_STRIKES) && Permissions.serratedStrikes(getPlayer());
     }
@@ -38,9 +42,7 @@ public class SwordsManager extends SkillManager {
      * @param target The defending entity
      */
     public void bleedCheck(LivingEntity target) {
-        Player player = getPlayer();
-
-        if (SkillUtils.activationSuccessful(player, skill, Swords.bleedMaxChance, Swords.bleedMaxBonusLevel)) {
+        if (SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Swords.bleedMaxChance, Swords.bleedMaxBonusLevel)) {
 
             if (getSkillLevel() >= Swords.bleedMaxBonusLevel) {
                 BleedTimerTask.add(target, Swords.bleedMaxTicks);
@@ -50,7 +52,7 @@ public class SwordsManager extends SkillManager {
             }
 
             if (mcMMOPlayer.useChatNotifications()) {
-                player.sendMessage(LocaleLoader.getString("Swords.Combat.Bleeding"));
+                getPlayer().sendMessage(LocaleLoader.getString("Swords.Combat.Bleeding"));
             }
 
             if (target instanceof Player) {
@@ -64,7 +66,7 @@ public class SwordsManager extends SkillManager {
     }
 
     public void counterAttackChecks(LivingEntity attacker, int damage) {
-        if (SkillUtils.activationSuccessful(getPlayer(), skill, Swords.counterAttackMaxChance, Swords.counterAttackMaxBonusLevel)) {
+        if (SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Swords.counterAttackMaxChance, Swords.counterAttackMaxBonusLevel)) {
             CombatUtils.dealDamage(attacker, damage / Swords.counterAttackModifier);
 
             getPlayer().sendMessage(LocaleLoader.getString("Swords.Combat.Countered"));

+ 21 - 11
src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java

@@ -27,23 +27,35 @@ public class TamingManager extends SkillManager {
     }
 
     public boolean canUseThickFur() {
-        return getSkillLevel() > Taming.thickFurUnlockLevel && Permissions.thickFur(getPlayer());
+        return getSkillLevel() >= Taming.thickFurUnlockLevel && Permissions.thickFur(getPlayer());
     }
 
     public boolean canUseEnvironmentallyAware() {
-        return getSkillLevel() > Taming.environmentallyAwareUnlockLevel && Permissions.environmentallyAware(getPlayer());
+        return getSkillLevel() >= Taming.environmentallyAwareUnlockLevel && Permissions.environmentallyAware(getPlayer());
     }
 
     public boolean canUseShockProof() {
-        return getSkillLevel() > Taming.shockProofUnlockLevel && Permissions.shockProof(getPlayer());
+        return getSkillLevel() >= Taming.shockProofUnlockLevel && Permissions.shockProof(getPlayer());
     }
 
     public boolean canUseHolyHound() {
-        return getSkillLevel() > Taming.holyHoundUnlockLevel && Permissions.holyHound(getPlayer());
+        return getSkillLevel() >= Taming.holyHoundUnlockLevel && Permissions.holyHound(getPlayer());
     }
 
-    public boolean canUseBeastLore(LivingEntity target) {
-        return target instanceof Tameable && Permissions.beastLore(getPlayer());
+    public boolean canUseFastFoodService() {
+        return getSkillLevel() >= Taming.fastFoodServiceUnlockLevel && Permissions.fastFoodService(getPlayer());
+    }
+
+    public boolean canUseSharpenedClaws() {
+        return getSkillLevel() >= Taming.sharpenedClawsUnlockLevel && Permissions.sharpenedClaws(getPlayer());
+    }
+
+    public boolean canUseGore() {
+        return Permissions.gore(getPlayer());
+    }
+
+    public boolean canUseBeastLore() {
+        return Permissions.beastLore(getPlayer());
     }
 
     /**
@@ -73,7 +85,7 @@ public class TamingManager extends SkillManager {
      * @param damage The damage being absorbed by the wolf
      */
     public void fastFoodService(Wolf wolf, int damage) {
-        if (SkillUtils.activationSuccessful(getPlayer(), skill, Taming.fastFoodServiceActivationChance)) {
+        if (getActivationChance() > Taming.fastFoodServiceActivationChance) {
 
             int health = wolf.getHealth();
             int maxHealth = wolf.getMaxHealth();
@@ -91,16 +103,14 @@ public class TamingManager extends SkillManager {
      * @param event The event to modify
      */
     public int gore(LivingEntity target, int damage) {
-        Player owner = getPlayer();
-
-        if (SkillUtils.activationSuccessful(owner, skill, Taming.goreMaxChance, Taming.goreMaxBonusLevel)) {
+        if (SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Taming.goreMaxChance, Taming.goreMaxBonusLevel)) {
             BleedTimerTask.add(target, Taming.goreBleedTicks);
 
             if (target instanceof Player) {
                 ((Player) target).sendMessage(LocaleLoader.getString("Combat.StruckByGore"));
             }
 
-            owner.sendMessage(LocaleLoader.getString("Combat.Gore"));
+            getPlayer().sendMessage(LocaleLoader.getString("Combat.Gore"));
             return damage * Taming.goreModifier;
         }
 

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

@@ -38,13 +38,19 @@ public class UnarmedManager extends SkillManager {
         return target instanceof Player && ((Player) target).getItemInHand().getType() != Material.AIR && Permissions.disarm(getPlayer());
     }
 
+    public boolean canDeflect() {
+        Player player = getPlayer();
+
+        return player.getItemInHand().getType() == Material.AIR && Permissions.arrowDeflect(player);
+    }
+
     /**
      * Check for disarm.
      *
      * @param defender The defending player
      */
     public void disarmCheck(Player defender) {
-        if (SkillUtils.activationSuccessful(getPlayer(), skill, Unarmed.disarmMaxChance, Unarmed.disarmMaxBonusLevel) && !hasIronGrip(defender)) {
+        if (SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Unarmed.disarmMaxChance, Unarmed.disarmMaxBonusLevel) && !hasIronGrip(defender)) {
             McMMOPlayerDisarmEvent disarmEvent = new McMMOPlayerDisarmEvent(defender);
             mcMMO.p.getServer().getPluginManager().callEvent(disarmEvent);
 
@@ -61,10 +67,8 @@ public class UnarmedManager extends SkillManager {
      * Check for arrow deflection.
      */
     public boolean deflectCheck() {
-        Player player = getPlayer();
-
-        if (SkillUtils.activationSuccessful(player, skill, Unarmed.deflectMaxChance, Unarmed.deflectMaxBonusLevel)) {
-            player.sendMessage(LocaleLoader.getString("Combat.ArrowDeflect"));
+        if (SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Unarmed.deflectMaxChance, Unarmed.deflectMaxBonusLevel)) {
+            getPlayer().sendMessage(LocaleLoader.getString("Combat.ArrowDeflect"));
             return true;
         }
 

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

@@ -55,22 +55,27 @@ public final class CombatUtils {
 
         if (attacker instanceof Player && damager.getType() == EntityType.PLAYER) {
             Player player = (Player) attacker;
-            McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
 
             if (Misc.isNPCEntity(player)) {
                 return;
             }
 
+            McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
             ItemStack heldItem = player.getItemInHand();
 
             if (target instanceof Tameable) {
-                if (heldItem.getType() == Material.BONE && Permissions.beastLore(player)) {
-                    mcMMOPlayer.getTamingManager().beastLore(target);
-                    event.setCancelled(true);
+                if (isFriendlyPet(player, (Tameable) target)) {
                     return;
                 }
-                else if (isFriendlyPet(player, (Tameable) target)) {
-                    return;
+
+                if (heldItem.getType() == Material.BONE) {
+                    TamingManager tamingManager = mcMMOPlayer.getTamingManager();
+
+                    if (tamingManager.canUseBeastLore()) {
+                        tamingManager.beastLore(target);
+                        event.setCancelled(true);
+                        return;
+                    }
                 }
             }
 
@@ -94,7 +99,7 @@ public final class CombatUtils {
                         swordsManager.serratedStrikes(target, event.getDamage());
                     }
 
-                    startGainXp(swordsManager.getMcMMOPlayer(), target, SkillType.SWORDS);
+                    startGainXp(mcMMOPlayer, target, SkillType.SWORDS);
                 }
             }
             else if (ItemUtils.isAxe(heldItem)) {
@@ -128,7 +133,7 @@ public final class CombatUtils {
                         axesManager.skullSplitterCheck(target, event.getDamage());
                     }
 
-                    startGainXp(axesManager.getMcMMOPlayer(), target, SkillType.AXES);
+                    startGainXp(mcMMOPlayer, target, SkillType.AXES);
                 }
             }
             else if (heldItem.getType() == Material.AIR) {
@@ -155,14 +160,7 @@ public final class CombatUtils {
                         unarmedManager.disarmCheck((Player) target);
                     }
 
-                    startGainXp(unarmedManager.getMcMMOPlayer(), target, SkillType.UNARMED);
-                }
-            }
-            else if (heldItem.getType() == Material.BONE) {
-                TamingManager tamingManager = mcMMOPlayer.getTamingManager();
-
-                if (tamingManager.canUseBeastLore(target)) {
-                    tamingManager.beastLore(target);
+                    startGainXp(mcMMOPlayer, target, SkillType.UNARMED);
                 }
             }
         }
@@ -185,17 +183,16 @@ public final class CombatUtils {
                     if (Permissions.skillEnabled(master, SkillType.TAMING)) {
                         McMMOPlayer mcMMOPlayer = UserManager.getPlayer(master);
                         TamingManager tamingManager = mcMMOPlayer.getTamingManager();
-                        int skillLevel = tamingManager.getSkillLevel();
 
-                        if (skillLevel >= Taming.fastFoodServiceUnlockLevel && Permissions.fastFoodService(master)) {
+                        if (tamingManager.canUseFastFoodService()) {
                             tamingManager.fastFoodService(wolf, event.getDamage());
                         }
 
-                        if (skillLevel >= Taming.sharpenedClawsUnlockLevel && Permissions.sharpenedClaws(master)) {
+                        if (tamingManager.canUseSharpenedClaws()) {
                             event.setDamage(Taming.sharpenedClaws(event.getDamage()));
                         }
 
-                        if (Permissions.gore(master)) {
+                        if (tamingManager.canUseGore()) {
                             event.setDamage(tamingManager.gore(target, event.getDamage()));
                         }
 
@@ -214,10 +211,47 @@ public final class CombatUtils {
                 }
 
                 if (!shouldProcessSkill(target, SkillType.ARCHERY)) {
-                    return;
+                    break;
+                }
+
+                Player player = (Player) shooter;
+
+                if (Misc.isNPCEntity(player)) {
+                    break;
+                }
+
+                if (Permissions.skillEnabled(player, SkillType.ARCHERY)) {
+                    McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
+                    ArcheryManager archeryManager = mcMMOPlayer.getArcheryManager();
+
+                    if (archeryManager.canSkillShot()) {
+                        event.setDamage(archeryManager.skillShotCheck(event.getDamage()));
+                    }
+
+                    if (target instanceof Player && SkillType.UNARMED.getPVPEnabled()) {
+                        UnarmedManager unarmedManager = UserManager.getPlayer((Player) target).getUnarmedManager();
+
+                        if (unarmedManager.canDeflect()) {
+                            event.setCancelled(mcMMOPlayer.getUnarmedManager().deflectCheck());
+
+                            if (event.isCancelled()) {
+                                return;
+                            }
+                        }
+                    }
+
+                    if (archeryManager.canDaze(target)) {
+                        event.setDamage(archeryManager.dazeCheck((Player) target, event.getDamage()));
+                    }
+
+                    if (archeryManager.canTrackArrows()) {
+                        archeryManager.trackArrows(target);
+                    }
+
+                    archeryManager.distanceXpBonus(target);
+                    startGainXp(mcMMOPlayer, target, SkillType.ARCHERY);
                 }
 
-                archeryCheck((Player) shooter, target, event);
                 break;
 
             default:
@@ -238,59 +272,17 @@ public final class CombatUtils {
                 event.setDamage(acrobaticsManager.dodgeCheck(event.getDamage()));
             }
 
-            ItemStack heldItem = player.getItemInHand();
-
-            if (damager instanceof Player) {
-                if (SkillType.SWORDS.getPVPEnabled() && ItemUtils.isSword(heldItem) && Permissions.counterAttack(player)) {
-                    mcMMOPlayer.getSwordsManager().counterAttackChecks((LivingEntity) damager, event.getDamage());
-                }
-            }
-            else {
-                if (SkillType.SWORDS.getPVEEnabled() && damager instanceof LivingEntity && ItemUtils.isSword(heldItem) && Permissions.counterAttack(player)) {
-                    mcMMOPlayer.getSwordsManager().counterAttackChecks((LivingEntity) damager, event.getDamage());
-                }
-            }
-        }
-    }
-
-    /**
-     * Process archery abilities.
-     *
-     * @param shooter The player shooting
-     * @param target The defending entity
-     * @param event The event to run the archery checks on.
-     */
-    private static void archeryCheck(Player shooter, LivingEntity target, EntityDamageByEntityEvent event) {
-        if (Misc.isNPCEntity(shooter)) {
-            return;
-        }
-
-        if (Permissions.skillEnabled(shooter, SkillType.ARCHERY)) {
-            McMMOPlayer mcMMOPlayer = UserManager.getPlayer(shooter);
-            ArcheryManager archeryManager = mcMMOPlayer.getArcheryManager();
-
-            if (archeryManager.canSkillShot()) {
-                event.setDamage(archeryManager.skillShotCheck(event.getDamage()));
-            }
-
-            if (target instanceof Player && SkillType.UNARMED.getPVPEnabled() && ((Player) target).getItemInHand().getType() == Material.AIR && Permissions.arrowDeflect((Player) target)) {
-                event.setCancelled(mcMMOPlayer.getUnarmedManager().deflectCheck());
-
-                if (event.isCancelled()) {
+            if (ItemUtils.isSword(player.getItemInHand())) {
+                if (!shouldProcessSkill(target, SkillType.SWORDS)) {
                     return;
                 }
-            }
 
-            if (archeryManager.canDaze(target)) {
-                event.setDamage(archeryManager.dazeCheck((Player) target, event.getDamage()));
-            }
+                SwordsManager swordsManager = mcMMOPlayer.getSwordsManager();
 
-            if (archeryManager.canTrackArrows()) {
-                archeryManager.trackArrows(target);
+                if (swordsManager.canUseCounterAttack()) {
+                    swordsManager.counterAttackChecks((LivingEntity) damager, event.getDamage());
+                }
             }
-
-            archeryManager.distanceXpBonus(target);
-            startGainXp(UserManager.getPlayer(shooter), target, SkillType.ARCHERY);
         }
     }
 
@@ -582,7 +574,7 @@ public final class CombatUtils {
         return false;
     }
 
-    private static boolean shouldProcessSkill(LivingEntity target, SkillType skill) {
+    public static boolean shouldProcessSkill(Entity target, SkillType skill) {
         boolean process;
 
         if (target instanceof Player || (target instanceof Tameable && ((Tameable) target).isTamed())) {

+ 2 - 6
src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java

@@ -612,12 +612,8 @@ public class SkillUtils {
         return chance > Misc.getRandom().nextInt(activationChance);
     }
 
-    public static boolean activationSuccessful(Player player, SkillType skill, double chance) {
-        return chance > Misc.getRandom().nextInt(PerksUtils.handleLuckyPerks(player, skill));
-    }
-
-    public static boolean unlockLevelReached(Player player, SkillType skill, int unlockLevel) {
-        return UserManager.getPlayer(player).getProfile().getSkillLevel(skill) > unlockLevel;
+    public static boolean activationSuccessful(int skillLevel, int activationChance, double maxChance, int maxLevel) {
+        return ((maxChance / maxLevel) * Math.min(skillLevel, maxLevel)) > Misc.getRandom().nextInt(activationChance);
     }
 
     public static boolean treasureDropSuccessful(double dropChance, int activationChance) {