mirror of
				https://github.com/mcMMO-Dev/mcMMO.git
				synced 2025-11-04 02:53:43 +01:00 
			
		
		
		
	RandomChanceUtil refactor part 1
This commit is contained in:
		@@ -27,6 +27,7 @@ Version 2.1.175
 | 
			
		||||
    Added 'Woodcutting.SubSkill.CleanCuts.Name' to locale
 | 
			
		||||
    Added 'Woodcutting.SubSkill.CleanCuts.Stat' to locale
 | 
			
		||||
    Added 'Woodcutting.SubSkill.CleanCuts.Description' to locale
 | 
			
		||||
    (Codebase) Major refactoring for how random chance was handled in the code
 | 
			
		||||
 | 
			
		||||
    Added 'General.PowerLevel.Skill_Mastery.Enabled' to config.yml which is used to enable or disable the mastery skills (will also disable the new power level command)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
package com.gmail.nossr50.api.exceptions;
 | 
			
		||||
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
 | 
			
		||||
public class ValueOutOfBoundsException extends RuntimeException {
 | 
			
		||||
    public ValueOutOfBoundsException(@NotNull String message) {
 | 
			
		||||
        super(message);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -6,9 +6,7 @@ import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill;
 | 
			
		||||
import com.gmail.nossr50.listeners.InteractionManager;
 | 
			
		||||
import com.gmail.nossr50.locale.LocaleLoader;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceSkill;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.text.TextComponentFactory;
 | 
			
		||||
import net.kyori.adventure.text.Component;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -31,7 +29,7 @@ public class AcrobaticsCommand extends SkillCommand {
 | 
			
		||||
    protected void dataCalculations(Player player, float skillValue) {
 | 
			
		||||
        // ACROBATICS_DODGE
 | 
			
		||||
        if (canDodge) {
 | 
			
		||||
            String[] dodgeStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.ACROBATICS_DODGE);
 | 
			
		||||
            String[] dodgeStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.ACROBATICS_DODGE);
 | 
			
		||||
            dodgeChance = dodgeStrings[0];
 | 
			
		||||
            dodgeChanceLucky = dodgeStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
@@ -61,18 +59,18 @@ public class AcrobaticsCommand extends SkillCommand {
 | 
			
		||||
                double rollChance, graceChance;
 | 
			
		||||
 | 
			
		||||
                //Chance to roll at half
 | 
			
		||||
                RandomChanceSkill roll_rcs  = new RandomChanceSkill(player, SubSkillType.ACROBATICS_ROLL);
 | 
			
		||||
                SkillProbabilityWrapper roll_rcs  = new SkillProbabilityWrapper(player, SubSkillType.ACROBATICS_ROLL);
 | 
			
		||||
 | 
			
		||||
                //Chance to graceful roll
 | 
			
		||||
                RandomChanceSkill grace_rcs = new RandomChanceSkill(player, SubSkillType.ACROBATICS_ROLL);
 | 
			
		||||
                grace_rcs.setSkillLevel(grace_rcs.getSkillLevel() * 2); //Double Odds
 | 
			
		||||
                SkillProbabilityWrapper grace_rcs = new SkillProbabilityWrapper(player, SubSkillType.ACROBATICS_ROLL);
 | 
			
		||||
                grace_rcs.setxPos(grace_rcs.getxPos() * 2); //Double Odds
 | 
			
		||||
 | 
			
		||||
                //Chance Stat Calculations
 | 
			
		||||
                rollChance       = RandomChanceUtil.getRandomChanceExecutionChance(roll_rcs);
 | 
			
		||||
                graceChance      = RandomChanceUtil.getRandomChanceExecutionChance(grace_rcs);
 | 
			
		||||
                //damageThreshold  = AdvancedConfig.getInstance().getRollDamageThreshold();
 | 
			
		||||
 | 
			
		||||
                String[] rollStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.ACROBATICS_ROLL);
 | 
			
		||||
                String[] rollStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.ACROBATICS_ROLL);
 | 
			
		||||
 | 
			
		||||
                //Format
 | 
			
		||||
                double rollChanceLucky  = rollChance * 1.333D;
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,6 @@ import com.gmail.nossr50.locale.LocaleLoader;
 | 
			
		||||
import com.gmail.nossr50.skills.archery.Archery;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.skills.CombatUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.text.TextComponentFactory;
 | 
			
		||||
import net.kyori.adventure.text.Component;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -33,14 +32,14 @@ public class ArcheryCommand extends SkillCommand {
 | 
			
		||||
    protected void dataCalculations(Player player, float skillValue) {
 | 
			
		||||
        // ARCHERY_ARROW_RETRIEVAL
 | 
			
		||||
        if (canRetrieve) {
 | 
			
		||||
            String[] retrieveStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.ARCHERY_ARROW_RETRIEVAL);
 | 
			
		||||
            String[] retrieveStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.ARCHERY_ARROW_RETRIEVAL);
 | 
			
		||||
            retrieveChance = retrieveStrings[0];
 | 
			
		||||
            retrieveChanceLucky = retrieveStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // ARCHERY_DAZE
 | 
			
		||||
        if (canDaze) {
 | 
			
		||||
            String[] dazeStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.ARCHERY_DAZE);
 | 
			
		||||
            String[] dazeStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.ARCHERY_DAZE);
 | 
			
		||||
            dazeChance = dazeStrings[0];
 | 
			
		||||
            dazeChanceLucky = dazeStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@ import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import com.gmail.nossr50.util.skills.CombatUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.text.TextComponentFactory;
 | 
			
		||||
import net.kyori.adventure.text.Component;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -48,7 +47,7 @@ public class AxesCommand extends SkillCommand {
 | 
			
		||||
        
 | 
			
		||||
        // CRITICAL HIT
 | 
			
		||||
        if (canCritical) {
 | 
			
		||||
            String[] criticalHitStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.AXES_CRITICAL_STRIKES);
 | 
			
		||||
            String[] criticalHitStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.AXES_CRITICAL_STRIKES);
 | 
			
		||||
            critChance = criticalHitStrings[0];
 | 
			
		||||
            critChanceLucky = criticalHitStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
 | 
			
		||||
import com.gmail.nossr50.locale.LocaleLoader;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.text.TextComponentFactory;
 | 
			
		||||
import net.kyori.adventure.text.Component;
 | 
			
		||||
import org.bukkit.Material;
 | 
			
		||||
@@ -45,7 +44,7 @@ public class HerbalismCommand extends SkillCommand {
 | 
			
		||||
        
 | 
			
		||||
        // DOUBLE DROPS
 | 
			
		||||
        if (canDoubleDrop) {
 | 
			
		||||
            String[] doubleDropStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.HERBALISM_DOUBLE_DROPS);
 | 
			
		||||
            String[] doubleDropStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.HERBALISM_DOUBLE_DROPS);
 | 
			
		||||
            doubleDropChance = doubleDropStrings[0];
 | 
			
		||||
            doubleDropChanceLucky = doubleDropStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
@@ -66,21 +65,21 @@ public class HerbalismCommand extends SkillCommand {
 | 
			
		||||
        if (canGreenThumbBlocks || canGreenThumbPlants) {
 | 
			
		||||
            greenThumbStage = RankUtils.getRank(player, SubSkillType.HERBALISM_GREEN_THUMB);
 | 
			
		||||
 | 
			
		||||
            String[] greenThumbStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.HERBALISM_GREEN_THUMB);
 | 
			
		||||
            String[] greenThumbStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.HERBALISM_GREEN_THUMB);
 | 
			
		||||
            greenThumbChance = greenThumbStrings[0];
 | 
			
		||||
            greenThumbChanceLucky = greenThumbStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // HYLIAN LUCK
 | 
			
		||||
        if (hasHylianLuck) {
 | 
			
		||||
            String[] hylianLuckStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.HERBALISM_HYLIAN_LUCK);
 | 
			
		||||
            String[] hylianLuckStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.HERBALISM_HYLIAN_LUCK);
 | 
			
		||||
            hylianLuckChance = hylianLuckStrings[0];
 | 
			
		||||
            hylianLuckChanceLucky = hylianLuckStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // SHROOM THUMB
 | 
			
		||||
        if (canShroomThumb) {
 | 
			
		||||
            String[] shroomThumbStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.HERBALISM_SHROOM_THUMB);
 | 
			
		||||
            String[] shroomThumbStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.HERBALISM_SHROOM_THUMB);
 | 
			
		||||
            shroomThumbChance = shroomThumbStrings[0];
 | 
			
		||||
            shroomThumbChanceLucky = shroomThumbStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ import com.gmail.nossr50.skills.mining.MiningManager;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.text.TextComponentFactory;
 | 
			
		||||
import net.kyori.adventure.text.Component;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -32,7 +31,7 @@ public class MiningCommand extends SkillCommand {
 | 
			
		||||
 | 
			
		||||
    private boolean canSuperBreaker;
 | 
			
		||||
    private boolean canDoubleDrop;
 | 
			
		||||
    private boolean canTripleDrop;
 | 
			
		||||
    private boolean canMotherLode;
 | 
			
		||||
    private boolean canBlast;
 | 
			
		||||
    private boolean canBiggerBombs;
 | 
			
		||||
    private boolean canDemoExpert;
 | 
			
		||||
@@ -56,16 +55,15 @@ public class MiningCommand extends SkillCommand {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Mastery TRIPLE DROPS
 | 
			
		||||
        if (canTripleDrop) {
 | 
			
		||||
            String[] masteryTripleDropStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.MINING_MOTHER_LODE);
 | 
			
		||||
        if (canMotherLode) {
 | 
			
		||||
            String[] masteryTripleDropStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.MINING_MOTHER_LODE);
 | 
			
		||||
            tripleDropChance = masteryTripleDropStrings[0];
 | 
			
		||||
            tripleDropChanceLucky = masteryTripleDropStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        // DOUBLE DROPS
 | 
			
		||||
        if (canDoubleDrop) {
 | 
			
		||||
            String[] doubleDropStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.MINING_DOUBLE_DROPS);
 | 
			
		||||
            String[] doubleDropStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.MINING_DOUBLE_DROPS);
 | 
			
		||||
            doubleDropChance = doubleDropStrings[0];
 | 
			
		||||
            doubleDropChanceLucky = doubleDropStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
@@ -84,7 +82,7 @@ public class MiningCommand extends SkillCommand {
 | 
			
		||||
        canBlast = RankUtils.hasUnlockedSubskill(player, SubSkillType.MINING_BLAST_MINING) && Permissions.remoteDetonation(player);
 | 
			
		||||
        canDemoExpert = RankUtils.hasUnlockedSubskill(player, SubSkillType.MINING_DEMOLITIONS_EXPERTISE) && Permissions.demolitionsExpertise(player);
 | 
			
		||||
        canDoubleDrop = Permissions.canUseSubSkill(player, SubSkillType.MINING_DOUBLE_DROPS);
 | 
			
		||||
        canTripleDrop = Permissions.canUseSubSkill(player, SubSkillType.MINING_MOTHER_LODE);
 | 
			
		||||
        canMotherLode = Permissions.canUseSubSkill(player, SubSkillType.MINING_MOTHER_LODE);
 | 
			
		||||
        canSuperBreaker = RankUtils.hasUnlockedSubskill(player, SubSkillType.MINING_SUPER_BREAKER) && Permissions.superBreaker(player);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -113,7 +111,7 @@ public class MiningCommand extends SkillCommand {
 | 
			
		||||
            //messages.add(LocaleLoader.getString("Mining.Effect.DropChance", doubleDropChance) + (isLucky ? LocaleLoader.getString("Perks.Lucky.Bonus", doubleDropChanceLucky) : ""));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(canTripleDrop) {
 | 
			
		||||
        if(canMotherLode) {
 | 
			
		||||
            messages.add(getStatMessage(SubSkillType.MINING_MOTHER_LODE, tripleDropChance)
 | 
			
		||||
                    + (isLucky ? LocaleLoader.getString("Perks.Lucky.Bonus", tripleDropChanceLucky) : ""));
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,6 @@ import com.gmail.nossr50.skills.repair.repairables.Repairable;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.text.TextComponentFactory;
 | 
			
		||||
import net.kyori.adventure.text.Component;
 | 
			
		||||
import org.bukkit.Material;
 | 
			
		||||
@@ -68,7 +67,7 @@ public class RepairCommand extends SkillCommand {
 | 
			
		||||
 | 
			
		||||
        // SUPER REPAIR
 | 
			
		||||
        if (canSuperRepair) {
 | 
			
		||||
            String[] superRepairStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.REPAIR_SUPER_REPAIR);
 | 
			
		||||
            String[] superRepairStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.REPAIR_SUPER_REPAIR);
 | 
			
		||||
            superRepairChance = superRepairStrings[0];
 | 
			
		||||
            superRepairChanceLucky = superRepairStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -219,7 +219,7 @@ public abstract class SkillCommand implements TabExecutor {
 | 
			
		||||
        return Math.min((int) skillValue, maxLevel) / rankChangeLevel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected String[] getAbilityDisplayValues(SkillActivationType skillActivationType, Player player, SubSkillType subSkill) {
 | 
			
		||||
    protected static String[] getAbilityDisplayValues(SkillActivationType skillActivationType, Player player, SubSkillType subSkill) {
 | 
			
		||||
        return RandomChanceUtil.calculateAbilityDisplayValues(skillActivationType, player, subSkill);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,6 @@ import com.gmail.nossr50.locale.LocaleLoader;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.text.TextComponentFactory;
 | 
			
		||||
import net.kyori.adventure.text.Component;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -39,14 +38,14 @@ public class SmeltingCommand extends SkillCommand {
 | 
			
		||||
 | 
			
		||||
        // FLUX MINING
 | 
			
		||||
        /*if (canFluxMine) {
 | 
			
		||||
            String[] fluxMiningStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.SMELTING_FLUX_MINING);
 | 
			
		||||
            String[] fluxMiningStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.SMELTING_FLUX_MINING);
 | 
			
		||||
            str_fluxMiningChance = fluxMiningStrings[0];
 | 
			
		||||
            str_fluxMiningChanceLucky = fluxMiningStrings[1];
 | 
			
		||||
        }*/
 | 
			
		||||
        
 | 
			
		||||
        // SECOND SMELT
 | 
			
		||||
        if (canSecondSmelt) {
 | 
			
		||||
            String[] secondSmeltStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.SMELTING_SECOND_SMELT);
 | 
			
		||||
            String[] secondSmeltStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.SMELTING_SECOND_SMELT);
 | 
			
		||||
            str_secondSmeltChance = secondSmeltStrings[0];
 | 
			
		||||
            str_secondSmeltChanceLucky = secondSmeltStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@ import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import com.gmail.nossr50.util.skills.CombatUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.text.TextComponentFactory;
 | 
			
		||||
import net.kyori.adventure.text.Component;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -37,7 +36,7 @@ public class SwordsCommand extends SkillCommand {
 | 
			
		||||
    protected void dataCalculations(Player player, float skillValue) {
 | 
			
		||||
        // SWORDS_COUNTER_ATTACK
 | 
			
		||||
        if (canCounter) {
 | 
			
		||||
            String[] counterStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.SWORDS_COUNTER_ATTACK);
 | 
			
		||||
            String[] counterStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.SWORDS_COUNTER_ATTACK);
 | 
			
		||||
            counterChance = counterStrings[0];
 | 
			
		||||
            counterChanceLucky = counterStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
@@ -46,7 +45,7 @@ public class SwordsCommand extends SkillCommand {
 | 
			
		||||
        if (canBleed) {
 | 
			
		||||
            bleedLength = UserManager.getPlayer(player).getSwordsManager().getRuptureBleedTicks();
 | 
			
		||||
 | 
			
		||||
            String[] bleedStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.SWORDS_RUPTURE);
 | 
			
		||||
            String[] bleedStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.SWORDS_RUPTURE);
 | 
			
		||||
            bleedChance = bleedStrings[0];
 | 
			
		||||
            bleedChanceLucky = bleedStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
 | 
			
		||||
import com.gmail.nossr50.locale.LocaleLoader;
 | 
			
		||||
import com.gmail.nossr50.skills.taming.Taming;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.text.TextComponentFactory;
 | 
			
		||||
import net.kyori.adventure.text.Component;
 | 
			
		||||
import org.bukkit.entity.EntityType;
 | 
			
		||||
@@ -35,7 +34,7 @@ public class TamingCommand extends SkillCommand {
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void dataCalculations(Player player, float skillValue) {
 | 
			
		||||
        if (canGore) {
 | 
			
		||||
            String[] goreStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.TAMING_GORE);
 | 
			
		||||
            String[] goreStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.TAMING_GORE);
 | 
			
		||||
            goreChance = goreStrings[0];
 | 
			
		||||
            goreChanceLucky = goreStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import com.gmail.nossr50.util.skills.CombatUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.text.TextComponentFactory;
 | 
			
		||||
import net.kyori.adventure.text.Component;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -40,7 +39,7 @@ public class UnarmedCommand extends SkillCommand {
 | 
			
		||||
    protected void dataCalculations(Player player, float skillValue) {
 | 
			
		||||
        // UNARMED_ARROW_DEFLECT
 | 
			
		||||
        if (canDeflect) {
 | 
			
		||||
            String[] deflectStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.UNARMED_ARROW_DEFLECT);
 | 
			
		||||
            String[] deflectStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.UNARMED_ARROW_DEFLECT);
 | 
			
		||||
            deflectChance = deflectStrings[0];
 | 
			
		||||
            deflectChanceLucky = deflectStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
@@ -54,7 +53,7 @@ public class UnarmedCommand extends SkillCommand {
 | 
			
		||||
 | 
			
		||||
        // UNARMED_DISARM
 | 
			
		||||
        if (canDisarm) {
 | 
			
		||||
            String[] disarmStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.UNARMED_DISARM);
 | 
			
		||||
            String[] disarmStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.UNARMED_DISARM);
 | 
			
		||||
            disarmChance = disarmStrings[0];
 | 
			
		||||
            disarmChanceLucky = disarmStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
@@ -66,7 +65,7 @@ public class UnarmedCommand extends SkillCommand {
 | 
			
		||||
 | 
			
		||||
        // IRON GRIP
 | 
			
		||||
        if (canIronGrip) {
 | 
			
		||||
            String[] ironGripStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.UNARMED_IRON_GRIP);
 | 
			
		||||
            String[] ironGripStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.UNARMED_IRON_GRIP);
 | 
			
		||||
            ironGripChance = ironGripStrings[0];
 | 
			
		||||
            ironGripChanceLucky = ironGripStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
 | 
			
		||||
import com.gmail.nossr50.locale.LocaleLoader;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.text.TextComponentFactory;
 | 
			
		||||
import net.kyori.adventure.text.Component;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -43,7 +42,7 @@ public class WoodcuttingCommand extends SkillCommand {
 | 
			
		||||
 | 
			
		||||
        //Clean Cuts
 | 
			
		||||
        if(canTripleDrop) {
 | 
			
		||||
            String[] tripleDropStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.WOODCUTTING_CLEAN_CUTS);
 | 
			
		||||
            String[] tripleDropStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.WOODCUTTING_CLEAN_CUTS);
 | 
			
		||||
            tripleDropChance = tripleDropStrings[0];
 | 
			
		||||
            tripleDropChanceLucky = tripleDropStrings[1];
 | 
			
		||||
        }
 | 
			
		||||
@@ -57,7 +56,7 @@ public class WoodcuttingCommand extends SkillCommand {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void setDoubleDropClassicChanceStrings(Player player) {
 | 
			
		||||
        String[] doubleDropStrings = getAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.WOODCUTTING_HARVEST_LUMBER);
 | 
			
		||||
        String[] doubleDropStrings = getAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.WOODCUTTING_HARVEST_LUMBER);
 | 
			
		||||
        doubleDropChance = doubleDropStrings[0];
 | 
			
		||||
        doubleDropChanceLucky = doubleDropStrings[1];
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -14,11 +14,10 @@ import com.gmail.nossr50.util.ItemUtils;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceSkill;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.random.SkillProbabilityType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.PerksUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import com.gmail.nossr50.util.sounds.SoundManager;
 | 
			
		||||
import com.gmail.nossr50.util.sounds.SoundType;
 | 
			
		||||
@@ -125,14 +124,14 @@ public class Roll extends AcrobaticsSubSkill {
 | 
			
		||||
        float skillValue = playerProfile.getSkillLevel(getPrimarySkill());
 | 
			
		||||
        boolean isLucky = Permissions.lucky(player, getPrimarySkill());
 | 
			
		||||
 | 
			
		||||
        String[] rollStrings = RandomChanceUtil.calculateAbilityDisplayValues(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.ACROBATICS_ROLL);
 | 
			
		||||
        String[] rollStrings = RandomChanceUtil.calculateAbilityDisplayValues(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.ACROBATICS_ROLL);
 | 
			
		||||
        rollChance = rollStrings[0];
 | 
			
		||||
        rollChanceLucky = rollStrings[1];
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Graceful is double the odds of a normal roll
 | 
			
		||||
         */
 | 
			
		||||
        String[] gracefulRollStrings = RandomChanceUtil.calculateAbilityDisplayValuesCustom(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, player, SubSkillType.ACROBATICS_ROLL, 2.0D);
 | 
			
		||||
        String[] gracefulRollStrings = RandomChanceUtil.calculateAbilityDisplayValuesCustom(SkillProbabilityType.DYNAMIC_CONFIGURABLE, player, SubSkillType.ACROBATICS_ROLL, 2.0D);
 | 
			
		||||
        gracefulRollChance = gracefulRollStrings[0];
 | 
			
		||||
        gracefulRollChanceLucky = gracefulRollStrings[1];
 | 
			
		||||
 | 
			
		||||
@@ -199,7 +198,7 @@ public class Roll extends AcrobaticsSubSkill {
 | 
			
		||||
        double modifiedDamage = calculateModifiedRollDamage(damage, AdvancedConfig.getInstance().getRollDamageThreshold());
 | 
			
		||||
 | 
			
		||||
        if (!isFatal(player, modifiedDamage)
 | 
			
		||||
                && RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.ACROBATICS_ROLL, player)) {
 | 
			
		||||
                && SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.ACROBATICS_ROLL, player)) {
 | 
			
		||||
            NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Acrobatics.Roll.Text");
 | 
			
		||||
            SoundManager.sendCategorizedSound(player, player.getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS);
 | 
			
		||||
            //player.sendMessage(LocaleLoader.getString("Acrobatics.Roll.Text"));
 | 
			
		||||
@@ -236,11 +235,11 @@ public class Roll extends AcrobaticsSubSkill {
 | 
			
		||||
    private double gracefulRollCheck(Player player, McMMOPlayer mcMMOPlayer, double damage, int skillLevel) {
 | 
			
		||||
        double modifiedDamage = calculateModifiedRollDamage(damage, AdvancedConfig.getInstance().getRollDamageThreshold() * 2);
 | 
			
		||||
 | 
			
		||||
        RandomChanceSkill rcs = new RandomChanceSkill(player, subSkillType);
 | 
			
		||||
        rcs.setSkillLevel(rcs.getSkillLevel() * 2); //Double the effective odds
 | 
			
		||||
        SkillProbabilityWrapper rcs = new SkillProbabilityWrapper(player, subSkillType);
 | 
			
		||||
        rcs.setxPos(rcs.getxPos() * 2); //Double the effective odds
 | 
			
		||||
 | 
			
		||||
        if (!isFatal(player, modifiedDamage)
 | 
			
		||||
                && RandomChanceUtil.checkRandomChanceExecutionSuccess(rcs))
 | 
			
		||||
                && RandomChanceUtil.processProbabilityResults(rcs))
 | 
			
		||||
        {
 | 
			
		||||
            NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Acrobatics.Ability.Proc");
 | 
			
		||||
            SoundManager.sendCategorizedSound(player, player.getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS,0.5F);
 | 
			
		||||
@@ -373,17 +372,17 @@ public class Roll extends AcrobaticsSubSkill {
 | 
			
		||||
        double rollChanceHalfMax, graceChanceHalfMax, damageThreshold, chancePerLevel;
 | 
			
		||||
 | 
			
		||||
        //Chance to roll at half max skill
 | 
			
		||||
        RandomChanceSkill rollHalfMaxSkill = new RandomChanceSkill(null, subSkillType);
 | 
			
		||||
        SkillProbabilityWrapper rollHalfMaxSkill = new SkillProbabilityWrapper(null, subSkillType);
 | 
			
		||||
        int halfMaxSkillValue = AdvancedConfig.getInstance().getMaxBonusLevel(SubSkillType.ACROBATICS_ROLL)/2;
 | 
			
		||||
        rollHalfMaxSkill.setSkillLevel(halfMaxSkillValue);
 | 
			
		||||
        rollHalfMaxSkill.setxPos(halfMaxSkillValue);
 | 
			
		||||
 | 
			
		||||
        //Chance to graceful roll at full skill
 | 
			
		||||
        RandomChanceSkill rollGraceHalfMaxSkill = new RandomChanceSkill(null, subSkillType);
 | 
			
		||||
        rollGraceHalfMaxSkill.setSkillLevel(halfMaxSkillValue * 2); //Double the effective odds
 | 
			
		||||
        SkillProbabilityWrapper rollGraceHalfMaxSkill = new SkillProbabilityWrapper(null, subSkillType);
 | 
			
		||||
        rollGraceHalfMaxSkill.setxPos(halfMaxSkillValue * 2); //Double the effective odds
 | 
			
		||||
 | 
			
		||||
        //Chance to roll per level
 | 
			
		||||
        RandomChanceSkill rollOneSkillLevel = new RandomChanceSkill(null, subSkillType);
 | 
			
		||||
        rollGraceHalfMaxSkill.setSkillLevel(1); //Level 1 skill
 | 
			
		||||
        SkillProbabilityWrapper rollOneSkillLevel = new SkillProbabilityWrapper(null, subSkillType);
 | 
			
		||||
        rollGraceHalfMaxSkill.setxPos(1); //Level 1 skill
 | 
			
		||||
 | 
			
		||||
        //Chance Stat Calculations
 | 
			
		||||
        rollChanceHalfMax       = RandomChanceUtil.getRandomChanceExecutionChance(rollHalfMaxSkill);
 | 
			
		||||
@@ -408,10 +407,10 @@ public class Roll extends AcrobaticsSubSkill {
 | 
			
		||||
    {
 | 
			
		||||
        double playerChanceRoll, playerChanceGrace;
 | 
			
		||||
 | 
			
		||||
        RandomChanceSkill roll          = new RandomChanceSkill(player, getSubSkillType());
 | 
			
		||||
        RandomChanceSkill graceful      = new RandomChanceSkill(player, getSubSkillType());
 | 
			
		||||
        SkillProbabilityWrapper roll          = new SkillProbabilityWrapper(player, getSubSkillType());
 | 
			
		||||
        SkillProbabilityWrapper graceful      = new SkillProbabilityWrapper(player, getSubSkillType());
 | 
			
		||||
 | 
			
		||||
        graceful.setSkillLevel(graceful.getSkillLevel() * 2); //Double odds
 | 
			
		||||
        graceful.setxPos(graceful.getxPos() * 2); //Double odds
 | 
			
		||||
 | 
			
		||||
        //Calculate
 | 
			
		||||
        playerChanceRoll        = RandomChanceUtil.getRandomChanceExecutionChance(roll);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,26 +1,37 @@
 | 
			
		||||
package com.gmail.nossr50.datatypes.treasure;
 | 
			
		||||
 | 
			
		||||
import com.gmail.nossr50.config.Config;
 | 
			
		||||
import com.gmail.nossr50.util.random.Probability;
 | 
			
		||||
import com.gmail.nossr50.util.random.ProbabilityFactory;
 | 
			
		||||
import com.gmail.nossr50.util.random.ProbabilityImpl;
 | 
			
		||||
import com.google.common.base.Objects;
 | 
			
		||||
import org.bukkit.inventory.ItemStack;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
 | 
			
		||||
public abstract class Treasure {
 | 
			
		||||
    private int xp;
 | 
			
		||||
    private double dropChance;
 | 
			
		||||
    private @NotNull Probability dropProbability;
 | 
			
		||||
    private int dropLevel;
 | 
			
		||||
    private ItemStack drop;
 | 
			
		||||
    private @NotNull ItemStack drop;
 | 
			
		||||
 | 
			
		||||
    public Treasure(ItemStack drop, int xp, double dropChance, int dropLevel) {
 | 
			
		||||
        this.drop = drop;
 | 
			
		||||
        this.xp = xp;
 | 
			
		||||
        this.dropChance = dropChance;
 | 
			
		||||
        this.dropProbability = new ProbabilityImpl(ProbabilityFactory.probabilityFromPercent(dropChance));
 | 
			
		||||
        this.dropLevel = dropLevel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ItemStack getDrop() {
 | 
			
		||||
    public @NotNull Probability getDropProbability() {
 | 
			
		||||
        return dropProbability;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public @NotNull ItemStack getDrop() {
 | 
			
		||||
        return drop;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setDrop(ItemStack drop) {
 | 
			
		||||
    public void setDrop(@NotNull ItemStack drop) {
 | 
			
		||||
        this.drop = drop;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -36,8 +47,9 @@ public abstract class Treasure {
 | 
			
		||||
        return dropChance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setDropChance(Double dropChance) {
 | 
			
		||||
    public void setDropChance(double dropChance) {
 | 
			
		||||
        this.dropChance = dropChance;
 | 
			
		||||
        this.dropProbability = new ProbabilityImpl(ProbabilityFactory.probabilityFromPercent(dropChance));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getDropLevel() {
 | 
			
		||||
@@ -51,4 +63,28 @@ public abstract class Treasure {
 | 
			
		||||
    public void setDropLevel(int dropLevel) {
 | 
			
		||||
        this.dropLevel = dropLevel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String toString() {
 | 
			
		||||
        return "Treasure{" +
 | 
			
		||||
                "xp=" + xp +
 | 
			
		||||
                ", dropChance=" + dropChance +
 | 
			
		||||
                ", dropProbability=" + dropProbability +
 | 
			
		||||
                ", dropLevel=" + dropLevel +
 | 
			
		||||
                ", drop=" + drop +
 | 
			
		||||
                '}';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean equals(Object o) {
 | 
			
		||||
        if (this == o) return true;
 | 
			
		||||
        if (o == null || getClass() != o.getClass()) return false;
 | 
			
		||||
        Treasure treasure = (Treasure) o;
 | 
			
		||||
        return xp == treasure.xp && Double.compare(treasure.dropChance, dropChance) == 0 && dropLevel == treasure.dropLevel && Objects.equal(dropProbability, treasure.dropProbability) && Objects.equal(drop, treasure.drop);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int hashCode() {
 | 
			
		||||
        return Objects.hashCode(xp, dropChance, dropProbability, dropLevel, drop);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,9 +25,8 @@ import com.gmail.nossr50.util.compat.layers.persistentdata.AbstractPersistentDat
 | 
			
		||||
import com.gmail.nossr50.util.compat.layers.persistentdata.MobMetaFlagType;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.CombatUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import com.gmail.nossr50.worldguard.WorldGuardManager;
 | 
			
		||||
import com.gmail.nossr50.worldguard.WorldGuardUtils;
 | 
			
		||||
import org.bukkit.Material;
 | 
			
		||||
@@ -180,7 +179,7 @@ public class EntityListener implements Listener {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.ARCHERY_ARROW_RETRIEVAL, player)) {
 | 
			
		||||
                if (SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.ARCHERY_ARROW_RETRIEVAL, player)) {
 | 
			
		||||
                    projectile.setMetadata(mcMMO.trackedArrow, mcMMO.metadataValue);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -12,10 +12,8 @@ import com.gmail.nossr50.skills.SkillManager;
 | 
			
		||||
import com.gmail.nossr50.util.Misc;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import org.bukkit.Location;
 | 
			
		||||
import org.bukkit.entity.Entity;
 | 
			
		||||
@@ -88,7 +86,7 @@ public class AcrobaticsManager extends SkillManager {
 | 
			
		||||
        double modifiedDamage = Acrobatics.calculateModifiedDodgeDamage(damage, Acrobatics.dodgeDamageModifier);
 | 
			
		||||
        Player player = getPlayer();
 | 
			
		||||
 | 
			
		||||
        if (!isFatal(modifiedDamage) && RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.ACROBATICS_DODGE, player)) {
 | 
			
		||||
        if (!isFatal(modifiedDamage) && SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.ACROBATICS_DODGE, player)) {
 | 
			
		||||
            ParticleEffectUtils.playDodgeEffect(player);
 | 
			
		||||
 | 
			
		||||
            if (mmoPlayer.useChatNotifications()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,9 @@ import com.gmail.nossr50.skills.SkillManager;
 | 
			
		||||
import com.gmail.nossr50.util.Misc;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import org.bukkit.Location;
 | 
			
		||||
import org.bukkit.entity.Entity;
 | 
			
		||||
import org.bukkit.entity.LivingEntity;
 | 
			
		||||
@@ -88,7 +88,7 @@ public class ArcheryManager extends SkillManager {
 | 
			
		||||
     * @param defender The {@link Player} being affected by the ability
 | 
			
		||||
     */
 | 
			
		||||
    public double daze(Player defender) {
 | 
			
		||||
        if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.ARCHERY_DAZE, getPlayer())) {
 | 
			
		||||
        if (!SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.ARCHERY_DAZE, getPlayer())) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -116,7 +116,7 @@ public class ArcheryManager extends SkillManager {
 | 
			
		||||
     * @param oldDamage The raw damage value of this arrow before we modify it
 | 
			
		||||
     */
 | 
			
		||||
    public double skillShot(double oldDamage) {
 | 
			
		||||
        if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.ARCHERY_SKILL_SHOT, getPlayer())) {
 | 
			
		||||
        if (!SkillUtils.isSkillRNGSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.ARCHERY_SKILL_SHOT, getPlayer())) {
 | 
			
		||||
            return oldDamage;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ import com.gmail.nossr50.skills.SkillManager;
 | 
			
		||||
import com.gmail.nossr50.util.ItemUtils;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.random.SkillProbabilityType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.*;
 | 
			
		||||
import org.bukkit.entity.LivingEntity;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -69,7 +69,7 @@ public class AxesManager extends SkillManager {
 | 
			
		||||
     * Handle the effects of the Axe Mastery ability
 | 
			
		||||
     */
 | 
			
		||||
    public double axeMastery() {
 | 
			
		||||
        if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.AXES_AXE_MASTERY, getPlayer())) {
 | 
			
		||||
        if (!SkillUtils.isSkillRNGSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.AXES_AXE_MASTERY, getPlayer())) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -83,7 +83,7 @@ public class AxesManager extends SkillManager {
 | 
			
		||||
     * @param damage The amount of damage initially dealt by the event
 | 
			
		||||
     */
 | 
			
		||||
    public double criticalHit(LivingEntity target, double damage) {
 | 
			
		||||
        if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.AXES_CRITICAL_STRIKES, getPlayer())) {
 | 
			
		||||
        if (!SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.AXES_CRITICAL_STRIKES, getPlayer())) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -119,7 +119,7 @@ public class AxesManager extends SkillManager {
 | 
			
		||||
 | 
			
		||||
        for (ItemStack armor : target.getEquipment().getArmorContents()) {
 | 
			
		||||
            if (armor != null && ItemUtils.isArmor(armor)) {
 | 
			
		||||
                if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_STATIC_CHANCE, SubSkillType.AXES_ARMOR_IMPACT, getPlayer())) {
 | 
			
		||||
                if (SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.AXES_ARMOR_IMPACT, getPlayer())) {
 | 
			
		||||
                    SkillUtils.handleDurabilityChange(armor, durabilityDamage, 1);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -137,7 +137,7 @@ public class AxesManager extends SkillManager {
 | 
			
		||||
     */
 | 
			
		||||
    public double greaterImpact(@NotNull LivingEntity target) {
 | 
			
		||||
        //static chance (3rd param)
 | 
			
		||||
        if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_STATIC_CHANCE, SubSkillType.AXES_GREATER_IMPACT, getPlayer())) {
 | 
			
		||||
        if (!SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.AXES_GREATER_IMPACT, getPlayer())) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ public class ExcavationManager extends SkillManager {
 | 
			
		||||
 | 
			
		||||
                for (ExcavationTreasure treasure : treasures) {
 | 
			
		||||
                    if (skillLevel >= treasure.getDropLevel()
 | 
			
		||||
                            && RandomChanceUtil.checkRandomChanceExecutionSuccess(getPlayer(), PrimarySkillType.EXCAVATION, treasure.getDropChance())) {
 | 
			
		||||
                            && SkillUtils.isStaticSkillRNGSuccessful(PrimarySkillType.EXCAVATION, getPlayer(), treasure.getDropProbability())) {
 | 
			
		||||
 | 
			
		||||
                        //Spawn Vanilla XP orbs if a dice roll succeeds
 | 
			
		||||
                        if(RandomChanceUtil.rollDice(getArchaelogyExperienceOrbChance(), 100)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,6 @@ import com.gmail.nossr50.skills.SkillManager;
 | 
			
		||||
import com.gmail.nossr50.util.*;
 | 
			
		||||
import com.gmail.nossr50.util.compat.layers.skills.MasterAnglerCompatibilityLayer;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.CombatUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
@@ -63,11 +61,14 @@ public class FishingManager extends SkillManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean canShake(Entity target) {
 | 
			
		||||
        return target instanceof LivingEntity && RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.FISHING_SHAKE) && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_SHAKE);
 | 
			
		||||
        return target instanceof LivingEntity && RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.FISHING_SHAKE)
 | 
			
		||||
                && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_SHAKE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean canMasterAngler() {
 | 
			
		||||
        return mcMMO.getCompatibilityManager().getMasterAnglerCompatibilityLayer() != null && getSkillLevel() >= RankUtils.getUnlockLevel(SubSkillType.FISHING_MASTER_ANGLER) && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_MASTER_ANGLER);
 | 
			
		||||
        return mcMMO.getCompatibilityManager().getMasterAnglerCompatibilityLayer() != null
 | 
			
		||||
                && getSkillLevel() >= RankUtils.getUnlockLevel(SubSkillType.FISHING_MASTER_ANGLER)
 | 
			
		||||
                && Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.FISHING_MASTER_ANGLER);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//    public void setFishingRodCastTimestamp()
 | 
			
		||||
@@ -477,8 +478,8 @@ public class FishingManager extends SkillManager {
 | 
			
		||||
     *
 | 
			
		||||
     * @param target The {@link LivingEntity} affected by the ability
 | 
			
		||||
     */
 | 
			
		||||
    public void shakeCheck(LivingEntity target) {
 | 
			
		||||
        if (RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getShakeChance(), getPlayer(), SubSkillType.FISHING_SHAKE))) {
 | 
			
		||||
    public void shakeCheck(@NotNull LivingEntity target) {
 | 
			
		||||
        if (SkillUtils.isStaticSkillRNGSuccessful(PrimarySkillType.FISHING, getPlayer(), getShakeChance())) {
 | 
			
		||||
            List<ShakeTreasure> possibleDrops = Fishing.findPossibleDrops(target);
 | 
			
		||||
 | 
			
		||||
            if (possibleDrops == null || possibleDrops.isEmpty()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -21,10 +21,8 @@ import com.gmail.nossr50.runnables.skills.DelayedHerbalismXPCheckTask;
 | 
			
		||||
import com.gmail.nossr50.skills.SkillManager;
 | 
			
		||||
import com.gmail.nossr50.util.*;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import com.gmail.nossr50.util.sounds.SoundManager;
 | 
			
		||||
import com.gmail.nossr50.util.sounds.SoundType;
 | 
			
		||||
@@ -589,7 +587,7 @@ public class HerbalismManager extends SkillManager {
 | 
			
		||||
     * @return true if the ability was successful, false otherwise
 | 
			
		||||
     */
 | 
			
		||||
    public boolean processGreenThumbBlocks(BlockState blockState) {
 | 
			
		||||
        if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.HERBALISM_GREEN_THUMB, getPlayer())) {
 | 
			
		||||
        if (!SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.HERBALISM_GREEN_THUMB, getPlayer())) {
 | 
			
		||||
            NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE_FAILED, "Herbalism.Ability.GTh.Fail");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
@@ -604,7 +602,7 @@ public class HerbalismManager extends SkillManager {
 | 
			
		||||
     * @return true if the ability was successful, false otherwise
 | 
			
		||||
     */
 | 
			
		||||
    public boolean processHylianLuck(BlockState blockState) {
 | 
			
		||||
        if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.HERBALISM_HYLIAN_LUCK, getPlayer())) {
 | 
			
		||||
        if (!SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.HERBALISM_HYLIAN_LUCK, getPlayer())) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -623,7 +621,7 @@ public class HerbalismManager extends SkillManager {
 | 
			
		||||
 | 
			
		||||
        for (HylianTreasure treasure : treasures) {
 | 
			
		||||
            if (skillLevel >= treasure.getDropLevel()
 | 
			
		||||
                    && RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(treasure.getDropChance(), getPlayer(), SubSkillType.HERBALISM_HYLIAN_LUCK))) {
 | 
			
		||||
                    && RandomChanceUtil.processProbabilityResults(new SkillProbabilityWrapperStatic(treasure.getDropChance(), getPlayer(), SubSkillType.HERBALISM_HYLIAN_LUCK))) {
 | 
			
		||||
                if (!EventUtils.simulateBlockBreak(blockState.getBlock(), player, false)) {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
@@ -660,7 +658,7 @@ public class HerbalismManager extends SkillManager {
 | 
			
		||||
        playerInventory.removeItem(new ItemStack(Material.RED_MUSHROOM));
 | 
			
		||||
        player.updateInventory();
 | 
			
		||||
 | 
			
		||||
        if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.HERBALISM_SHROOM_THUMB, player)) {
 | 
			
		||||
        if (!SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.HERBALISM_SHROOM_THUMB, player)) {
 | 
			
		||||
            NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Herbalism.Ability.ShroomThumb.Fail");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -16,10 +16,8 @@ import com.gmail.nossr50.util.EventUtils;
 | 
			
		||||
import com.gmail.nossr50.util.Misc;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import com.gmail.nossr50.util.sounds.SoundManager;
 | 
			
		||||
import com.gmail.nossr50.util.sounds.SoundType;
 | 
			
		||||
@@ -291,7 +289,7 @@ public class RepairManager extends SkillManager {
 | 
			
		||||
        if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.REPAIR_SUPER_REPAIR))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.REPAIR_SUPER_REPAIR, getPlayer())) {
 | 
			
		||||
        if (SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.REPAIR_SUPER_REPAIR, getPlayer())) {
 | 
			
		||||
            NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Repair.Skills.FeltEasy");
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
@@ -342,10 +340,10 @@ public class RepairManager extends SkillManager {
 | 
			
		||||
 | 
			
		||||
            Enchantment enchantment = enchant.getKey();
 | 
			
		||||
 | 
			
		||||
            if (RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getKeepEnchantChance(), getPlayer(), SubSkillType.REPAIR_ARCANE_FORGING))) {
 | 
			
		||||
            if (RandomChanceUtil.processProbabilityResults(new SkillProbabilityWrapperStatic(getKeepEnchantChance(), getPlayer(), SubSkillType.REPAIR_ARCANE_FORGING))) {
 | 
			
		||||
 | 
			
		||||
                if (ArcaneForging.arcaneForgingDowngrades && enchantLevel > 1
 | 
			
		||||
                        && (!RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(100 - getDowngradeEnchantChance(), getPlayer(), SubSkillType.REPAIR_ARCANE_FORGING)))) {
 | 
			
		||||
                        && (!RandomChanceUtil.processProbabilityResults(new SkillProbabilityWrapperStatic(100 - getDowngradeEnchantChance(), getPlayer(), SubSkillType.REPAIR_ARCANE_FORGING)))) {
 | 
			
		||||
                    item.addUnsafeEnchantment(enchantment, enchantLevel - 1);
 | 
			
		||||
                    downgraded = true;
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,6 @@ import com.gmail.nossr50.util.EventUtils;
 | 
			
		||||
import com.gmail.nossr50.util.Misc;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
@@ -123,7 +122,7 @@ public class SalvageManager extends SkillManager {
 | 
			
		||||
 | 
			
		||||
        for(int x = 0; x < potentialSalvageYield-1; x++) {
 | 
			
		||||
 | 
			
		||||
            if(RandomChanceUtil.rollDice(chanceOfSuccess, 100)) {
 | 
			
		||||
            if(RandomChanceUtil.rollDiceSimple(chanceOfSuccess, 100)) {
 | 
			
		||||
                chanceOfSuccess-=3;
 | 
			
		||||
                chanceOfSuccess = Math.max(chanceOfSuccess, 90);
 | 
			
		||||
 | 
			
		||||
@@ -253,12 +252,12 @@ public class SalvageManager extends SkillManager {
 | 
			
		||||
 | 
			
		||||
            if (!Salvage.arcaneSalvageEnchantLoss
 | 
			
		||||
                    || Permissions.hasSalvageEnchantBypassPerk(player)
 | 
			
		||||
                    || RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getExtractFullEnchantChance(), getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE))) {
 | 
			
		||||
                    || RandomChanceUtil.processProbabilityResults(new SkillProbabilityWrapperStatic(getExtractFullEnchantChance(), getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE))) {
 | 
			
		||||
                enchantMeta.addStoredEnchant(enchant.getKey(), enchantLevel, true);
 | 
			
		||||
            }
 | 
			
		||||
            else if (enchantLevel > 1
 | 
			
		||||
                    && Salvage.arcaneSalvageDowngrades
 | 
			
		||||
                    && RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getExtractPartialEnchantChance(), getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE))) {
 | 
			
		||||
                    && RandomChanceUtil.processProbabilityResults(new SkillProbabilityWrapperStatic(getExtractPartialEnchantChance(), getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE))) {
 | 
			
		||||
                enchantMeta.addStoredEnchant(enchant.getKey(), enchantLevel - 1, true);
 | 
			
		||||
                downgraded = true;
 | 
			
		||||
            } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,9 +8,8 @@ import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 | 
			
		||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
 | 
			
		||||
import com.gmail.nossr50.skills.SkillManager;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import org.bukkit.event.inventory.FurnaceBurnEvent;
 | 
			
		||||
import org.bukkit.inventory.ItemStack;
 | 
			
		||||
 | 
			
		||||
@@ -28,7 +27,7 @@ public class SmeltingManager extends SkillManager {
 | 
			
		||||
 | 
			
		||||
    public boolean isSecondSmeltSuccessful() {
 | 
			
		||||
        return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.SMELTING_SECOND_SMELT)
 | 
			
		||||
                && RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.SMELTING_SECOND_SMELT, getPlayer());
 | 
			
		||||
                && SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.SMELTING_SECOND_SMELT, getPlayer());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
 
 | 
			
		||||
@@ -11,10 +11,9 @@ import com.gmail.nossr50.skills.SkillManager;
 | 
			
		||||
import com.gmail.nossr50.util.ItemUtils;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.CombatUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import org.bukkit.entity.Entity;
 | 
			
		||||
import org.bukkit.entity.LivingEntity;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -62,7 +61,7 @@ public class SwordsManager extends SkillManager {
 | 
			
		||||
     */
 | 
			
		||||
    public void ruptureCheck(@NotNull LivingEntity target) throws IllegalStateException {
 | 
			
		||||
        if(BleedTimerTask.isBleedOperationAllowed()) {
 | 
			
		||||
            if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.SWORDS_RUPTURE, getPlayer())) {
 | 
			
		||||
            if (SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.SWORDS_RUPTURE, getPlayer())) {
 | 
			
		||||
 | 
			
		||||
                if (target instanceof Player) {
 | 
			
		||||
                    Player defender = (Player) target;
 | 
			
		||||
@@ -129,7 +128,7 @@ public class SwordsManager extends SkillManager {
 | 
			
		||||
     * @param damage The amount of damage initially dealt by the event
 | 
			
		||||
     */
 | 
			
		||||
    public void counterAttackChecks(@NotNull LivingEntity attacker, double damage) {
 | 
			
		||||
        if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.SWORDS_COUNTER_ATTACK, getPlayer())) {
 | 
			
		||||
        if (SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.SWORDS_COUNTER_ATTACK, getPlayer())) {
 | 
			
		||||
            CombatUtils.dealDamage(attacker, damage / Swords.counterAttackModifier, getPlayer());
 | 
			
		||||
 | 
			
		||||
            NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.Countered");
 | 
			
		||||
 
 | 
			
		||||
@@ -18,11 +18,10 @@ import com.gmail.nossr50.util.Misc;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.compat.layers.persistentdata.MobMetaFlagType;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import com.gmail.nossr50.util.sounds.SoundManager;
 | 
			
		||||
import com.gmail.nossr50.util.sounds.SoundType;
 | 
			
		||||
import com.gmail.nossr50.util.text.StringUtils;
 | 
			
		||||
@@ -147,7 +146,7 @@ public class TamingManager extends SkillManager {
 | 
			
		||||
     * @param damage The damage being absorbed by the wolf
 | 
			
		||||
     */
 | 
			
		||||
    public void fastFoodService(@NotNull Wolf wolf, double damage) {
 | 
			
		||||
        if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_STATIC_CHANCE, SubSkillType.TAMING_FAST_FOOD_SERVICE, getPlayer())) {
 | 
			
		||||
        if (!SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.TAMING_FAST_FOOD_SERVICE, getPlayer())) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -168,7 +167,7 @@ public class TamingManager extends SkillManager {
 | 
			
		||||
     */
 | 
			
		||||
    public double gore(@NotNull LivingEntity target, double damage) {
 | 
			
		||||
        if(BleedTimerTask.isBleedOperationAllowed()) {
 | 
			
		||||
            if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.TAMING_GORE, getPlayer())) {
 | 
			
		||||
            if (!SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.TAMING_GORE, getPlayer())) {
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -276,7 +275,7 @@ public class TamingManager extends SkillManager {
 | 
			
		||||
        if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.TAMING_PUMMEL))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if(!RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(AdvancedConfig.getInstance().getPummelChance(), getPlayer(), SubSkillType.TAMING_PUMMEL)))
 | 
			
		||||
        if(!RandomChanceUtil.processProbabilityResults(new SkillProbabilityWrapperStatic(AdvancedConfig.getInstance().getPummelChance(), getPlayer(), SubSkillType.TAMING_PUMMEL)))
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        ParticleEffectUtils.playGreaterImpactEffect(target);
 | 
			
		||||
 
 | 
			
		||||
@@ -16,9 +16,9 @@ import com.gmail.nossr50.util.Misc;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import org.bukkit.Material;
 | 
			
		||||
import org.bukkit.block.BlockState;
 | 
			
		||||
import org.bukkit.entity.Item;
 | 
			
		||||
@@ -72,7 +72,7 @@ public class UnarmedManager extends SkillManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean blockCrackerCheck(@NotNull BlockState blockState) {
 | 
			
		||||
        if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.UNARMED_BLOCK_CRACKER, getPlayer())) {
 | 
			
		||||
        if (!SkillUtils.isSkillRNGSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.UNARMED_BLOCK_CRACKER, getPlayer())) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -103,7 +103,7 @@ public class UnarmedManager extends SkillManager {
 | 
			
		||||
     * @param defender The defending player
 | 
			
		||||
     */
 | 
			
		||||
    public void disarmCheck(@NotNull Player defender) {
 | 
			
		||||
        if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.UNARMED_DISARM, getPlayer()) && !hasIronGrip(defender)) {
 | 
			
		||||
        if (SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.UNARMED_DISARM, getPlayer()) && !hasIronGrip(defender)) {
 | 
			
		||||
            if (EventUtils.callDisarmEvent(defender).isCancelled()) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
@@ -126,7 +126,7 @@ public class UnarmedManager extends SkillManager {
 | 
			
		||||
     * Check for arrow deflection.
 | 
			
		||||
     */
 | 
			
		||||
    public boolean deflectCheck() {
 | 
			
		||||
        if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.UNARMED_ARROW_DEFLECT, getPlayer())) {
 | 
			
		||||
        if (SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.UNARMED_ARROW_DEFLECT, getPlayer())) {
 | 
			
		||||
            NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Combat.ArrowDeflect");
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
@@ -149,7 +149,7 @@ public class UnarmedManager extends SkillManager {
 | 
			
		||||
     * Handle the effects of the Iron Arm ability
 | 
			
		||||
     */
 | 
			
		||||
    public double calculateSteelArmStyleDamage() {
 | 
			
		||||
        if (!RandomChanceUtil.isActivationSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.UNARMED_STEEL_ARM_STYLE, getPlayer())) {
 | 
			
		||||
        if (!SkillUtils.isSkillRNGSuccessful(SkillActivationType.ALWAYS_FIRES, SubSkillType.UNARMED_STEEL_ARM_STYLE, getPlayer())) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -183,7 +183,7 @@ public class UnarmedManager extends SkillManager {
 | 
			
		||||
    private boolean hasIronGrip(@NotNull Player defender) {
 | 
			
		||||
        if (!Misc.isNPCEntityExcludingVillagers(defender)
 | 
			
		||||
                && Permissions.isSubSkillEnabled(defender, SubSkillType.UNARMED_IRON_GRIP)
 | 
			
		||||
                && RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.UNARMED_IRON_GRIP, defender)) {
 | 
			
		||||
                && SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.UNARMED_IRON_GRIP, defender)) {
 | 
			
		||||
            NotificationManager.sendPlayerInformation(defender, NotificationType.SUBSKILL_MESSAGE, "Unarmed.Ability.IronGrip.Defender");
 | 
			
		||||
            NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Unarmed.Ability.IronGrip.Attacker");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@ import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.CombatUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.Material;
 | 
			
		||||
@@ -70,11 +69,11 @@ public class WoodcuttingManager extends SkillManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean checkHarvestLumberActivation() {
 | 
			
		||||
        return RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.WOODCUTTING_HARVEST_LUMBER, getPlayer());
 | 
			
		||||
        return SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.WOODCUTTING_HARVEST_LUMBER, getPlayer());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean checkCleanCutsActivation() {
 | 
			
		||||
        return RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.WOODCUTTING_CLEAN_CUTS, getPlayer());
 | 
			
		||||
        return SkillUtils.isSkillRNGSuccessful(SkillProbabilityType.DYNAMIC_CONFIGURABLE, SubSkillType.WOODCUTTING_CLEAN_CUTS, getPlayer());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -328,7 +327,7 @@ public class WoodcuttingManager extends SkillManager {
 | 
			
		||||
 | 
			
		||||
                    if(RankUtils.hasReachedRank(2, player, SubSkillType.WOODCUTTING_KNOCK_ON_WOOD)) {
 | 
			
		||||
                        if(AdvancedConfig.getInstance().isKnockOnWoodXPOrbEnabled()) {
 | 
			
		||||
                            if(RandomChanceUtil.rollDice(10, 100)) {
 | 
			
		||||
                            if(RandomChanceUtil.rollDiceSimple(10, 100)) {
 | 
			
		||||
                                int randOrbCount = Math.max(1, Misc.getRandom().nextInt(100));
 | 
			
		||||
                                Misc.spawnExperienceOrb(blockState.getLocation(), randOrbCount);
 | 
			
		||||
                            }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
 | 
			
		||||
import com.gmail.nossr50.mcMMO;
 | 
			
		||||
import com.gmail.nossr50.skills.repair.Repair;
 | 
			
		||||
import com.gmail.nossr50.skills.salvage.Salvage;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceSkill;
 | 
			
		||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
 | 
			
		||||
import org.bukkit.Material;
 | 
			
		||||
import org.bukkit.block.Block;
 | 
			
		||||
@@ -55,7 +54,7 @@ public final class BlockUtils {
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean checkDoubleDrops(Player player, BlockState blockState, PrimarySkillType skillType, SubSkillType subSkillType) {
 | 
			
		||||
        if (Config.getInstance().getDoubleDropsEnabled(skillType, blockState.getType()) && Permissions.isSubSkillEnabled(player, subSkillType)) {
 | 
			
		||||
            return RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType, true));
 | 
			
		||||
            return RandomChanceUtil.processProbabilityResults(new SkillProbabilityWrapper(player, subSkillType, true));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
 
 | 
			
		||||
@@ -344,4 +344,26 @@ public final class Misc {
 | 
			
		||||
            experienceOrb.setExperience(orbExpValue);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//    public static void hackyUnitTest(@NotNull McMMOPlayer normalPlayer) {
 | 
			
		||||
//        mcMMO.p.getLogger().info("Starting hacky unit test...");
 | 
			
		||||
//        int iterations = 1000000;
 | 
			
		||||
//        double ratioDivisor = 10000; //10000 because we run the test 1,000,000 times
 | 
			
		||||
//        double expectedFailRate = 100.0D - RandomChanceUtil.getRandomChanceExecutionSuccess(normalPlayer.getPlayer(), SubSkillType.MINING_MOTHER_LODE, true);
 | 
			
		||||
//
 | 
			
		||||
//        double win = 0, loss = 0;
 | 
			
		||||
//        for(int x = 0; x < iterations; x++) {
 | 
			
		||||
//            if(RandomChanceUtil.checkRandomChanceExecutionSuccess(normalPlayer.getPlayer(), SubSkillType.MINING_MOTHER_LODE, true)) {
 | 
			
		||||
//                win++;
 | 
			
		||||
//            } else {
 | 
			
		||||
//                loss++;
 | 
			
		||||
//            }
 | 
			
		||||
//        }
 | 
			
		||||
//
 | 
			
		||||
//        double lossRatio = (loss / ratioDivisor);
 | 
			
		||||
//        mcMMO.p.getLogger().info("Expected Fail Rate: "+expectedFailRate);
 | 
			
		||||
//        mcMMO.p.getLogger().info("Loss Ratio for hacky test: "+lossRatio);
 | 
			
		||||
////        Assert.assertEquals(lossRatio, expectedFailRate, 0.01D);
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								src/main/java/com/gmail/nossr50/util/random/Probability.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/main/java/com/gmail/nossr50/util/random/Probability.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
package com.gmail.nossr50.util.random;
 | 
			
		||||
 | 
			
		||||
public interface Probability {
 | 
			
		||||
    /**
 | 
			
		||||
     * The value of this Probability
 | 
			
		||||
     * Should return a result between 0 and 1 (inclusive)
 | 
			
		||||
     * 1 should represent something that will always succeed
 | 
			
		||||
     * 0.5 should represent something that succeeds around half the time
 | 
			
		||||
     * etc
 | 
			
		||||
     *
 | 
			
		||||
     * @return the value of probability
 | 
			
		||||
     */
 | 
			
		||||
    double getValue();
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,77 @@
 | 
			
		||||
package com.gmail.nossr50.util.random;
 | 
			
		||||
 | 
			
		||||
import com.gmail.nossr50.config.AdvancedConfig;
 | 
			
		||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 | 
			
		||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
import org.jetbrains.annotations.Nullable;
 | 
			
		||||
 | 
			
		||||
public class ProbabilityFactory {
 | 
			
		||||
 | 
			
		||||
    public static @NotNull Probability ofPercentageValue(double percentageValue) {
 | 
			
		||||
        return new ProbabilityImpl(probabilityFromPercent(percentageValue));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static @NotNull Probability ofSubSkill(@Nullable Player player,
 | 
			
		||||
                                                  @NotNull SubSkillType subSkillType,
 | 
			
		||||
                                                  @NotNull SkillProbabilityType skillProbabilityType) throws InvalidStaticChance, RuntimeException {
 | 
			
		||||
 | 
			
		||||
        switch (skillProbabilityType) {
 | 
			
		||||
            case DYNAMIC_CONFIGURABLE:
 | 
			
		||||
                double probabilityCeiling;
 | 
			
		||||
                double xCeiling;
 | 
			
		||||
                double xPos;
 | 
			
		||||
 | 
			
		||||
                if (player != null) {
 | 
			
		||||
                    McMMOPlayer mmoPlayer = UserManager.getPlayer(player);
 | 
			
		||||
                    if(mmoPlayer != null)
 | 
			
		||||
                        xPos = mmoPlayer.getSkillLevel(subSkillType.getParentSkill());
 | 
			
		||||
                    else
 | 
			
		||||
                        xPos = 0;
 | 
			
		||||
                } else {
 | 
			
		||||
                    xPos = 0;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                //Probability ceiling is configurable in this type
 | 
			
		||||
                probabilityCeiling = AdvancedConfig.getInstance().getMaximumProbability(subSkillType);
 | 
			
		||||
                //The xCeiling is configurable in this type
 | 
			
		||||
                xCeiling = AdvancedConfig.getInstance().getMaxBonusLevel(subSkillType);
 | 
			
		||||
                return new ProbabilityImpl(xPos, xCeiling, probabilityCeiling);
 | 
			
		||||
            case STATIC_CONFIGURABLE:
 | 
			
		||||
                return ofPercentageValue(getStaticRandomChance(subSkillType));
 | 
			
		||||
            default:
 | 
			
		||||
                throw new RuntimeException("No case in switch statement for Skill Probability Type!");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Convert a probability from a percentage
 | 
			
		||||
     * @param percentage value to convert
 | 
			
		||||
     * @return 0 -> 1 inclusive representation of probability
 | 
			
		||||
     */
 | 
			
		||||
    public static double probabilityFromPercent(double percentage) {
 | 
			
		||||
        return percentage / 100;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Grabs static activation rolls for Secondary Abilities
 | 
			
		||||
     *
 | 
			
		||||
     * @param subSkillType The secondary ability to grab properties of
 | 
			
		||||
     * @return The static activation roll involved in the RNG calculation
 | 
			
		||||
     * @throws InvalidStaticChance if the skill has no defined static chance this exception will be thrown and you should know you're a naughty boy
 | 
			
		||||
     */
 | 
			
		||||
    private static double getStaticRandomChance(@NotNull SubSkillType subSkillType) throws InvalidStaticChance {
 | 
			
		||||
        switch (subSkillType) {
 | 
			
		||||
            case AXES_ARMOR_IMPACT:
 | 
			
		||||
                return AdvancedConfig.getInstance().getImpactChance();
 | 
			
		||||
            case AXES_GREATER_IMPACT:
 | 
			
		||||
                return AdvancedConfig.getInstance().getGreaterImpactChance();
 | 
			
		||||
            case TAMING_FAST_FOOD_SERVICE:
 | 
			
		||||
                return AdvancedConfig.getInstance().getFastFoodChance();
 | 
			
		||||
            default:
 | 
			
		||||
                throw new InvalidStaticChance();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,63 @@
 | 
			
		||||
package com.gmail.nossr50.util.random;
 | 
			
		||||
 | 
			
		||||
import com.gmail.nossr50.api.exceptions.ValueOutOfBoundsException;
 | 
			
		||||
import com.google.common.base.Objects;
 | 
			
		||||
 | 
			
		||||
public class ProbabilityImpl implements Probability {
 | 
			
		||||
 | 
			
		||||
    private final double probabilityValue;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a probability with a static value
 | 
			
		||||
     *
 | 
			
		||||
     * @param staticProbability the value to assign to this probability
 | 
			
		||||
     */
 | 
			
		||||
    public ProbabilityImpl(double staticProbability) throws ValueOutOfBoundsException {
 | 
			
		||||
        if(staticProbability > 1) {
 | 
			
		||||
            throw new ValueOutOfBoundsException("Value should never be above 1 for Probability! This suggests a coding mistake, contact the devs!");
 | 
			
		||||
        } else if (staticProbability < 0) {
 | 
			
		||||
            throw new ValueOutOfBoundsException("Value should never be negative for Probability! This suggests a coding mistake, contact the devs!");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        probabilityValue = staticProbability;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ProbabilityImpl(double xPos, double xCeiling, double probabilityCeiling) throws ValueOutOfBoundsException {
 | 
			
		||||
        if(probabilityCeiling > 100) {
 | 
			
		||||
            throw new ValueOutOfBoundsException("Probability Ceiling should never be above 100!");
 | 
			
		||||
        } else if (probabilityCeiling < 0) {
 | 
			
		||||
            throw new ValueOutOfBoundsException("Probability Ceiling should never be below 0!");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Get the percent success, this will be from 0-100
 | 
			
		||||
        double probabilityPercent = (probabilityCeiling * (xPos / xCeiling));
 | 
			
		||||
 | 
			
		||||
        //Convert to a 0-1 floating point representation
 | 
			
		||||
        this.probabilityValue = probabilityPercent / 100.0D;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public double getValue() {
 | 
			
		||||
        return probabilityValue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String toString() {
 | 
			
		||||
        return "ProbabilityImpl{" +
 | 
			
		||||
                "probabilityValue=" + probabilityValue +
 | 
			
		||||
                '}';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean equals(Object o) {
 | 
			
		||||
        if (this == o) return true;
 | 
			
		||||
        if (o == null || getClass() != o.getClass()) return false;
 | 
			
		||||
        ProbabilityImpl that = (ProbabilityImpl) o;
 | 
			
		||||
        return Double.compare(that.probabilityValue, probabilityValue) == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int hashCode() {
 | 
			
		||||
        return Objects.hashCode(probabilityValue);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,18 +0,0 @@
 | 
			
		||||
package com.gmail.nossr50.util.random;
 | 
			
		||||
 | 
			
		||||
public interface RandomChanceExecution {
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the XPos used in the formula for success
 | 
			
		||||
     *
 | 
			
		||||
     * @return value of x for our success probability graph
 | 
			
		||||
     */
 | 
			
		||||
    double getXPos();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The maximum odds for this RandomChanceExecution
 | 
			
		||||
     * For example, if this value is 10, then 10% odds would be the maximum and would be achieved only when xPos equaled the LinearCurvePeak
 | 
			
		||||
     *
 | 
			
		||||
     * @return maximum probability odds from 0.00 (no chance of ever happened) to 100.0 (probability can be guaranteed)
 | 
			
		||||
     */
 | 
			
		||||
    double getProbabilityCap();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,176 +0,0 @@
 | 
			
		||||
package com.gmail.nossr50.util.random;
 | 
			
		||||
 | 
			
		||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 | 
			
		||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
import org.jetbrains.annotations.Nullable;
 | 
			
		||||
 | 
			
		||||
public class RandomChanceSkill implements RandomChanceExecution {
 | 
			
		||||
    protected final double probabilityCap;
 | 
			
		||||
    protected final boolean isLucky;
 | 
			
		||||
    protected int skillLevel;
 | 
			
		||||
    protected final double resultModifier;
 | 
			
		||||
    protected final double maximumBonusLevelCap;
 | 
			
		||||
 | 
			
		||||
    public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, double resultModifier) {
 | 
			
		||||
        this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
 | 
			
		||||
 | 
			
		||||
        final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
 | 
			
		||||
        if (player != null && mcMMOPlayer != null) {
 | 
			
		||||
            this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
 | 
			
		||||
        } else {
 | 
			
		||||
            this.skillLevel = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (player != null)
 | 
			
		||||
            isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
 | 
			
		||||
        else
 | 
			
		||||
            isLucky = false;
 | 
			
		||||
 | 
			
		||||
        this.resultModifier = resultModifier;
 | 
			
		||||
        this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType) {
 | 
			
		||||
        this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
 | 
			
		||||
 | 
			
		||||
        final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
 | 
			
		||||
        if (player != null && mcMMOPlayer != null) {
 | 
			
		||||
            this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
 | 
			
		||||
        } else {
 | 
			
		||||
            this.skillLevel = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (player != null)
 | 
			
		||||
            isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
 | 
			
		||||
        else
 | 
			
		||||
            isLucky = false;
 | 
			
		||||
 | 
			
		||||
        this.resultModifier = 1.0D;
 | 
			
		||||
        this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap) {
 | 
			
		||||
        if (hasCap)
 | 
			
		||||
            this.probabilityCap = RandomChanceUtil.getMaximumProbability(subSkillType);
 | 
			
		||||
        else
 | 
			
		||||
            this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
 | 
			
		||||
 | 
			
		||||
        final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
 | 
			
		||||
        if (player != null && mcMMOPlayer != null) {
 | 
			
		||||
            this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
 | 
			
		||||
        } else {
 | 
			
		||||
            this.skillLevel = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (player != null)
 | 
			
		||||
            isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
 | 
			
		||||
        else
 | 
			
		||||
            isLucky = false;
 | 
			
		||||
 | 
			
		||||
        this.resultModifier = 1.0D;
 | 
			
		||||
        this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, boolean luckyOverride) {
 | 
			
		||||
        if (hasCap)
 | 
			
		||||
            this.probabilityCap = RandomChanceUtil.getMaximumProbability(subSkillType);
 | 
			
		||||
        else
 | 
			
		||||
            this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
 | 
			
		||||
 | 
			
		||||
        final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
 | 
			
		||||
        if (player != null && mcMMOPlayer != null) {
 | 
			
		||||
            this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
 | 
			
		||||
        } else {
 | 
			
		||||
            this.skillLevel = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        isLucky = luckyOverride;
 | 
			
		||||
 | 
			
		||||
        this.resultModifier = 1.0D;
 | 
			
		||||
        this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public RandomChanceSkill(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, double resultModifier) {
 | 
			
		||||
        if (hasCap)
 | 
			
		||||
            this.probabilityCap = RandomChanceUtil.getMaximumProbability(subSkillType);
 | 
			
		||||
        else
 | 
			
		||||
            this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
 | 
			
		||||
 | 
			
		||||
        final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
 | 
			
		||||
        if (player != null && mcMMOPlayer != null) {
 | 
			
		||||
            this.skillLevel = mcMMOPlayer.getSkillLevel(subSkillType.getParentSkill());
 | 
			
		||||
        } else {
 | 
			
		||||
            this.skillLevel = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (player != null)
 | 
			
		||||
            isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
 | 
			
		||||
        else
 | 
			
		||||
            isLucky = false;
 | 
			
		||||
 | 
			
		||||
        this.resultModifier = resultModifier;
 | 
			
		||||
        this.maximumBonusLevelCap = RandomChanceUtil.getMaxBonusLevelCap(subSkillType);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the skill level of the player who owns this RandomChanceSkill
 | 
			
		||||
     *
 | 
			
		||||
     * @return the current skill level relating to this RandomChanceSkill
 | 
			
		||||
     */
 | 
			
		||||
    public int getSkillLevel() {
 | 
			
		||||
        return skillLevel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Modify the skill level used for this skill's RNG calculations
 | 
			
		||||
     *
 | 
			
		||||
     * @param newSkillLevel new skill level
 | 
			
		||||
     */
 | 
			
		||||
    public void setSkillLevel(int newSkillLevel) {
 | 
			
		||||
        skillLevel = newSkillLevel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The maximum bonus level for this skill
 | 
			
		||||
     * This is when the skills level no longer increases the odds of success
 | 
			
		||||
     * For example, a value of 25 will mean the success chance no longer grows after skill level 25
 | 
			
		||||
     *
 | 
			
		||||
     * @return the maximum bonus from skill level for this skill
 | 
			
		||||
     */
 | 
			
		||||
    public double getMaximumBonusLevelCap() {
 | 
			
		||||
        return maximumBonusLevelCap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the XPos used in the formula for success
 | 
			
		||||
     *
 | 
			
		||||
     * @return value of x for our success probability graph
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public double getXPos() {
 | 
			
		||||
        return getSkillLevel();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The maximum odds for this RandomChanceExecution
 | 
			
		||||
     * For example, if this value is 10, then 10% odds would be the maximum and would be achieved only when xPos equaled the LinearCurvePeak
 | 
			
		||||
     *
 | 
			
		||||
     * @return maximum probability odds from 0.00 (no chance of ever happened) to 100.0 (probability can be guaranteed)
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public double getProbabilityCap() {
 | 
			
		||||
        return probabilityCap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isLucky() {
 | 
			
		||||
        return isLucky;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public double getResultModifier() {
 | 
			
		||||
        return resultModifier;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,61 +0,0 @@
 | 
			
		||||
package com.gmail.nossr50.util.random;
 | 
			
		||||
 | 
			
		||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
import org.jetbrains.annotations.Nullable;
 | 
			
		||||
 | 
			
		||||
public class RandomChanceSkillStatic extends RandomChanceSkill {
 | 
			
		||||
    private final double xPos;
 | 
			
		||||
 | 
			
		||||
    public RandomChanceSkillStatic(double xPos, @Nullable Player player, @NotNull SubSkillType subSkillType) {
 | 
			
		||||
        super(player, subSkillType);
 | 
			
		||||
 | 
			
		||||
        this.xPos = xPos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public RandomChanceSkillStatic(double xPos, @Nullable Player player, @NotNull SubSkillType subSkillType, boolean luckyOverride) {
 | 
			
		||||
        super(player, subSkillType, false, luckyOverride);
 | 
			
		||||
 | 
			
		||||
        this.xPos = xPos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public RandomChanceSkillStatic(double xPos, @Nullable Player player, @NotNull SubSkillType subSkillType, double resultModifier) {
 | 
			
		||||
        super(player, subSkillType, resultModifier);
 | 
			
		||||
 | 
			
		||||
        this.xPos = xPos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the XPos used in the formula for success
 | 
			
		||||
     *
 | 
			
		||||
     * @return value of x for our success probability graph
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public double getXPos() {
 | 
			
		||||
        return xPos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The maximum odds for this RandomChanceExecution
 | 
			
		||||
     * For example, if this value is 10, then 10% odds would be the maximum and would be achieved only when xPos equaled the LinearCurvePeak
 | 
			
		||||
     *
 | 
			
		||||
     * @return maximum probability odds from 0.00 (no chance of ever happened) to 100.0 (probability can be guaranteed)
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public double getProbabilityCap() {
 | 
			
		||||
        return probabilityCap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The maximum bonus level for this skill
 | 
			
		||||
     * This is when the skills level no longer increases the odds of success
 | 
			
		||||
     * For example, a value of 25 will mean the success chance no longer grows after skill level 25
 | 
			
		||||
     *
 | 
			
		||||
     * @return the maximum bonus from skill level for this skill
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public double getMaximumBonusLevelCap() {
 | 
			
		||||
        return 100;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,38 +0,0 @@
 | 
			
		||||
package com.gmail.nossr50.util.random;
 | 
			
		||||
 | 
			
		||||
public class RandomChanceStatic implements RandomChanceExecution {
 | 
			
		||||
    private final double xPos;
 | 
			
		||||
    private final double probabilityCap;
 | 
			
		||||
    private final boolean isLucky;
 | 
			
		||||
 | 
			
		||||
    public RandomChanceStatic(double xPos, boolean isLucky) {
 | 
			
		||||
        this.xPos = xPos;
 | 
			
		||||
        this.probabilityCap = xPos;
 | 
			
		||||
        this.isLucky = isLucky;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the XPos used in the formula for success
 | 
			
		||||
     *
 | 
			
		||||
     * @return value of x for our success probability graph
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public double getXPos() {
 | 
			
		||||
        return xPos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The maximum odds for this RandomChanceExecution
 | 
			
		||||
     * For example, if this value is 10, then 10% odds would be the maximum and would be achieved only when xPos equaled the LinearCurvePeak
 | 
			
		||||
     *
 | 
			
		||||
     * @return maximum probability odds from 0.00 (no chance of ever happened) to 100.0 (probability can be guaranteed)
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public double getProbabilityCap() {
 | 
			
		||||
        return probabilityCap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isLucky() {
 | 
			
		||||
        return isLucky;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,325 +1,78 @@
 | 
			
		||||
package com.gmail.nossr50.util.random;
 | 
			
		||||
 | 
			
		||||
import com.gmail.nossr50.config.AdvancedConfig;
 | 
			
		||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
 | 
			
		||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
 | 
			
		||||
import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillEvent;
 | 
			
		||||
import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillRandomCheckEvent;
 | 
			
		||||
import com.gmail.nossr50.util.EventUtils;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillActivationType;
 | 
			
		||||
import com.gmail.nossr50.util.skills.SkillUtils;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
import org.jetbrains.annotations.Nullable;
 | 
			
		||||
 | 
			
		||||
import java.text.DecimalFormat;
 | 
			
		||||
import java.util.concurrent.ThreadLocalRandom;
 | 
			
		||||
 | 
			
		||||
//TODO: Normalize chance values
 | 
			
		||||
//TODO: Test the 2 types of SkillProbabilityTypes
 | 
			
		||||
//TODO: Update calls to this class and its members
 | 
			
		||||
public class RandomChanceUtil {
 | 
			
		||||
    public static final @NotNull DecimalFormat percent = new DecimalFormat("##0.00%");
 | 
			
		||||
    //public static final DecimalFormat decimal = new DecimalFormat("##0.00");
 | 
			
		||||
    public static final double LINEAR_CURVE_VAR = 100.0D;
 | 
			
		||||
    public static final double LUCKY_MODIFIER = 1.333D;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This method is the final step in determining if a Sub-Skill / Secondary Skill in mcMMO successfully activates either from chance or otherwise
 | 
			
		||||
     * Random skills check for success based on numbers and then fire a cancellable event, if that event is not cancelled they succeed
 | 
			
		||||
     * non-RNG skills just fire the cancellable event and succeed if they go uncancelled
 | 
			
		||||
     * Simulate an outcome on a probability and return true or false for the result of that outcome
 | 
			
		||||
     *
 | 
			
		||||
     * @param skillActivationType this value represents what kind of activation procedures this sub-skill uses
 | 
			
		||||
     * @param subSkillType        The identifier for this specific sub-skill
 | 
			
		||||
     * @param player              The owner of this sub-skill
 | 
			
		||||
     * @return returns true if all conditions are met and the event is not cancelled
 | 
			
		||||
     * @param probability target probability
 | 
			
		||||
     * @return true if the probability succeeded, false if it failed
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isActivationSuccessful(@NotNull SkillActivationType skillActivationType, @NotNull SubSkillType subSkillType, @Nullable Player player) {
 | 
			
		||||
        switch (skillActivationType) {
 | 
			
		||||
            case RANDOM_LINEAR_100_SCALE_WITH_CAP:
 | 
			
		||||
                return checkRandomChanceExecutionSuccess(player, subSkillType, true);
 | 
			
		||||
            case RANDOM_STATIC_CHANCE:
 | 
			
		||||
                return checkRandomStaticChanceExecutionSuccess(player, subSkillType);
 | 
			
		||||
            case ALWAYS_FIRES:
 | 
			
		||||
                SubSkillEvent event = EventUtils.callSubSkillEvent(player, subSkillType);
 | 
			
		||||
                return !event.isCancelled();
 | 
			
		||||
            default:
 | 
			
		||||
                return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double getActivationChance(@NotNull SkillActivationType skillActivationType, @NotNull SubSkillType subSkillType, @Nullable Player player, boolean luckyOverride) {
 | 
			
		||||
        switch (skillActivationType) {
 | 
			
		||||
            case RANDOM_LINEAR_100_SCALE_WITH_CAP:
 | 
			
		||||
                return getRandomChanceExecutionSuccess(player, subSkillType, true, luckyOverride);
 | 
			
		||||
            case RANDOM_STATIC_CHANCE:
 | 
			
		||||
                return getRandomStaticChanceExecutionSuccess(player, subSkillType, luckyOverride);
 | 
			
		||||
            default:
 | 
			
		||||
                return 0.1337;
 | 
			
		||||
        }
 | 
			
		||||
    public static boolean processProbability(@NotNull Probability probability) {
 | 
			
		||||
        return isSuccessfulRoll(probability.getValue());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks whether or not the random chance succeeds
 | 
			
		||||
     * Modify and then Simulate an outcome on a probability and return true or false for the result of that outcome
 | 
			
		||||
     *
 | 
			
		||||
     * @return true if the random chance succeeds
 | 
			
		||||
     * @param probability target probability
 | 
			
		||||
     * @param probabilityMultiplier probability will be multiplied by this before success is checked
 | 
			
		||||
     * @return true if the probability succeeded, false if it failed
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean checkRandomChanceExecutionSuccess(@NotNull Player player, @NotNull PrimarySkillType primarySkillType, double chance) {
 | 
			
		||||
        //Check the odds
 | 
			
		||||
        chance *= 100;
 | 
			
		||||
 | 
			
		||||
        chance = addLuck(player, primarySkillType, chance);
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Stuff like treasures can specify a drop chance from 0.05 to 100
 | 
			
		||||
         * Because of that we need to use a large int bound and multiply the chance by 100
 | 
			
		||||
         */
 | 
			
		||||
        return rollDice(chance, 10000);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean rollDice(double chanceOfSuccess, int bound) {
 | 
			
		||||
        return rollDice(chanceOfSuccess, bound, 1.0F);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean rollDice(double chanceOfSuccess, int bound, double resultModifier) {
 | 
			
		||||
        return chanceOfSuccess > (ThreadLocalRandom.current().nextInt(bound) * resultModifier);
 | 
			
		||||
    public static boolean processProbability(@NotNull Probability probability, double probabilityMultiplier) {
 | 
			
		||||
        double probabilityValue = probability.getValue() * probabilityMultiplier;
 | 
			
		||||
        return isSuccessfulRoll(probabilityValue);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Used for stuff like Excavation, Fishing, etc...
 | 
			
		||||
     * Simulates a "roll of the dice"
 | 
			
		||||
     * If the value passed is higher than the "random" value, than it is a successful roll
 | 
			
		||||
     *
 | 
			
		||||
     * @param randomChance
 | 
			
		||||
     * @return
 | 
			
		||||
     * @param probabilityValue probability value
 | 
			
		||||
     * @return true for succeeding, false for failing
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean checkRandomChanceExecutionSuccess(@NotNull RandomChanceSkillStatic randomChance, double resultModifier) {
 | 
			
		||||
        double chanceOfSuccess = calculateChanceOfSuccess(randomChance);
 | 
			
		||||
 | 
			
		||||
        //Check the odds
 | 
			
		||||
        return rollDice(chanceOfSuccess, 100, resultModifier);
 | 
			
		||||
    private static boolean isSuccessfulRoll(double probabilityValue) {
 | 
			
		||||
        return probabilityValue >= ThreadLocalRandom.current().nextDouble(1.0D);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Used for stuff like Excavation, Fishing, etc...
 | 
			
		||||
     * Return a chance of success in "percentage" format, show to the player in UI elements
 | 
			
		||||
     *
 | 
			
		||||
     * @param randomChance
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean checkRandomChanceExecutionSuccess(@NotNull RandomChanceSkillStatic randomChance) {
 | 
			
		||||
        return checkRandomChanceExecutionSuccess(randomChance, 1.0F);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean checkRandomChanceExecutionSuccess(@NotNull RandomChanceSkill randomChance) {
 | 
			
		||||
        double chanceOfSuccess = calculateChanceOfSuccess(randomChance);
 | 
			
		||||
 | 
			
		||||
        //Check the odds
 | 
			
		||||
        return rollDice(chanceOfSuccess, 100);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the Static Chance for something to activate
 | 
			
		||||
     * @param player target player
 | 
			
		||||
     * @param subSkillType target subskill
 | 
			
		||||
     * @param isLucky whether or not to apply luck modifiers
 | 
			
		||||
     *
 | 
			
		||||
     * @param randomChance
 | 
			
		||||
     * @return
 | 
			
		||||
     * @return "percentage" representation of success
 | 
			
		||||
     */
 | 
			
		||||
    public static double getRandomChanceExecutionChance(@NotNull RandomChanceExecution randomChance) {
 | 
			
		||||
        return getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap(), LINEAR_CURVE_VAR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double getRandomChanceExecutionChance(@NotNull RandomChanceExecution randomChance, boolean luckyOverride) {
 | 
			
		||||
        return getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap(), LINEAR_CURVE_VAR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double getRandomChanceExecutionChance(@NotNull RandomChanceStatic randomChance) {
 | 
			
		||||
        double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap(), LINEAR_CURVE_VAR);
 | 
			
		||||
 | 
			
		||||
        chanceOfSuccess = addLuck(randomChance.isLucky(), chanceOfSuccess);
 | 
			
		||||
 | 
			
		||||
        return chanceOfSuccess;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double calculateChanceOfSuccess(@NotNull RandomChanceSkill randomChance) {
 | 
			
		||||
        double skillLevel = randomChance.getSkillLevel();
 | 
			
		||||
        double maximumProbability = randomChance.getProbabilityCap();
 | 
			
		||||
        double maximumBonusLevel = randomChance.getMaximumBonusLevelCap();
 | 
			
		||||
 | 
			
		||||
        double chanceOfSuccess;
 | 
			
		||||
 | 
			
		||||
        if (skillLevel >= maximumBonusLevel) {
 | 
			
		||||
            //Chance of success is equal to the maximum probability if the maximum bonus level has been reached
 | 
			
		||||
            chanceOfSuccess = maximumProbability;
 | 
			
		||||
        } else {
 | 
			
		||||
            //Get chance of success
 | 
			
		||||
            chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), maximumProbability, maximumBonusLevel);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Add Luck
 | 
			
		||||
        chanceOfSuccess = addLuck(randomChance.isLucky(), chanceOfSuccess);
 | 
			
		||||
 | 
			
		||||
        return chanceOfSuccess;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double calculateChanceOfSuccess(@NotNull RandomChanceSkillStatic randomChance) {
 | 
			
		||||
        double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), 100, 100);
 | 
			
		||||
 | 
			
		||||
        //Add Luck
 | 
			
		||||
        chanceOfSuccess = addLuck(randomChance.isLucky(), chanceOfSuccess);
 | 
			
		||||
 | 
			
		||||
        return chanceOfSuccess;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The formula for RNG success is determined like this
 | 
			
		||||
     * maximum probability * ( x / maxlevel )
 | 
			
		||||
     *
 | 
			
		||||
     * @return the chance of success from 0-100 (100 = guaranteed)
 | 
			
		||||
     */
 | 
			
		||||
    private static int getChanceOfSuccess(double skillLevel, double maxProbability, double maxLevel) {
 | 
			
		||||
        //return (int) (x / (y / LINEAR_CURVE_VAR));
 | 
			
		||||
        return (int) (maxProbability * (skillLevel / maxLevel));
 | 
			
		||||
        // max probability * (weight/maxlevel) = chance of success
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static int getChanceOfSuccess(double x, double y) {
 | 
			
		||||
        return (int) (x / (y / LINEAR_CURVE_VAR));
 | 
			
		||||
        // max probability * (weight/maxlevel) = chance of success
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double getRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap) {
 | 
			
		||||
        RandomChanceSkill rcs = new RandomChanceSkill(player, subSkillType, hasCap);
 | 
			
		||||
        return calculateChanceOfSuccess(rcs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double getRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, boolean luckyOverride) {
 | 
			
		||||
        RandomChanceSkill rcs = new RandomChanceSkill(player, subSkillType, hasCap, luckyOverride);
 | 
			
		||||
        return calculateChanceOfSuccess(rcs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double getRandomStaticChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean luckyOverride) {
 | 
			
		||||
    private static double chanceOfSuccessPercentage(@NotNull Player player, @NotNull SubSkillType subSkillType, boolean isLucky) {
 | 
			
		||||
        try {
 | 
			
		||||
            return getRandomChanceExecutionChance(new RandomChanceSkillStatic(getStaticRandomChance(subSkillType), player, subSkillType, luckyOverride));
 | 
			
		||||
            Probability probability = SkillUtils.getSubSkillProbability(subSkillType, player);
 | 
			
		||||
            //Probability values are on a 0-1 scale and need to be "transformed" into a 1-100 scale
 | 
			
		||||
            double percentageValue = probability.getValue() * 100;
 | 
			
		||||
 | 
			
		||||
            //Apply lucky modifier
 | 
			
		||||
            if(isLucky) {
 | 
			
		||||
                percentageValue *= LUCKY_MODIFIER;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return percentageValue;
 | 
			
		||||
        } catch (InvalidStaticChance invalidStaticChance) {
 | 
			
		||||
            //Catch invalid static skills
 | 
			
		||||
            invalidStaticChance.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return 0.1337; //Puts on shades
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean checkRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap) {
 | 
			
		||||
        return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType, hasCap));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean checkRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType) {
 | 
			
		||||
        return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean checkRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, boolean hasCap, double resultModifier) {
 | 
			
		||||
        return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType, hasCap, resultModifier));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean checkRandomChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType, double resultModifier) {
 | 
			
		||||
        return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType, resultModifier));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public static boolean checkRandomStaticChanceExecutionSuccess(@Nullable Player player, @NotNull SubSkillType subSkillType) {
 | 
			
		||||
        try {
 | 
			
		||||
            return checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getStaticRandomChance(subSkillType), player, subSkillType));
 | 
			
		||||
        } catch (InvalidStaticChance invalidStaticChance) {
 | 
			
		||||
            //Catch invalid static skills
 | 
			
		||||
            invalidStaticChance.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Grabs static activation rolls for Secondary Abilities
 | 
			
		||||
     *
 | 
			
		||||
     * @param subSkillType The secondary ability to grab properties of
 | 
			
		||||
     * @return The static activation roll involved in the RNG calculation
 | 
			
		||||
     * @throws InvalidStaticChance if the skill has no defined static chance this exception will be thrown and you should know you're a naughty boy
 | 
			
		||||
     */
 | 
			
		||||
    public static double getStaticRandomChance(@NotNull SubSkillType subSkillType) throws InvalidStaticChance {
 | 
			
		||||
        switch (subSkillType) {
 | 
			
		||||
            case AXES_ARMOR_IMPACT:
 | 
			
		||||
                return AdvancedConfig.getInstance().getImpactChance();
 | 
			
		||||
            case AXES_GREATER_IMPACT:
 | 
			
		||||
                return AdvancedConfig.getInstance().getGreaterImpactChance();
 | 
			
		||||
            case TAMING_FAST_FOOD_SERVICE:
 | 
			
		||||
                return AdvancedConfig.getInstance().getFastFoodChance();
 | 
			
		||||
            default:
 | 
			
		||||
                throw new InvalidStaticChance();
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean sendSkillEvent(Player player, SubSkillType subSkillType, double activationChance) {
 | 
			
		||||
        SubSkillRandomCheckEvent event = new SubSkillRandomCheckEvent(player, subSkillType, activationChance);
 | 
			
		||||
        return !event.isCancelled();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String @NotNull [] calculateAbilityDisplayValues(@NotNull SkillActivationType skillActivationType, @NotNull Player player, @NotNull SubSkillType subSkillType) {
 | 
			
		||||
        double successChance = getActivationChance(skillActivationType, subSkillType, player, false);
 | 
			
		||||
        double successChanceLucky = getActivationChance(skillActivationType, subSkillType, player, true);
 | 
			
		||||
 | 
			
		||||
        String[] displayValues = new String[2];
 | 
			
		||||
 | 
			
		||||
        boolean isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
 | 
			
		||||
 | 
			
		||||
        displayValues[0] = percent.format(Math.min(successChance, 100.0D) / 100.0D);
 | 
			
		||||
        displayValues[1] = isLucky ? percent.format(Math.min(successChanceLucky, 100.0D) / 100.0D) : null;
 | 
			
		||||
 | 
			
		||||
        return displayValues;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String @NotNull [] calculateAbilityDisplayValuesStatic(@NotNull Player player, @NotNull PrimarySkillType primarySkillType, double chance) {
 | 
			
		||||
        RandomChanceStatic rcs = new RandomChanceStatic(chance, false);
 | 
			
		||||
        double successChance = getRandomChanceExecutionChance(rcs);
 | 
			
		||||
 | 
			
		||||
        RandomChanceStatic rcs_lucky = new RandomChanceStatic(chance, true);
 | 
			
		||||
        double successChance_lucky = getRandomChanceExecutionChance(rcs_lucky);
 | 
			
		||||
 | 
			
		||||
        String[] displayValues = new String[2];
 | 
			
		||||
 | 
			
		||||
        boolean isLucky = Permissions.lucky(player, primarySkillType);
 | 
			
		||||
 | 
			
		||||
        displayValues[0] = percent.format(Math.min(successChance, 100.0D) / 100.0D);
 | 
			
		||||
        displayValues[1] = isLucky ? percent.format(Math.min(successChance_lucky, 100.0D) / 100.0D) : null;
 | 
			
		||||
 | 
			
		||||
        return displayValues;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String @NotNull [] calculateAbilityDisplayValuesCustom(@NotNull SkillActivationType skillActivationType, @NotNull Player player, @NotNull SubSkillType subSkillType, double multiplier) {
 | 
			
		||||
        double successChance = getActivationChance(skillActivationType, subSkillType, player, false);
 | 
			
		||||
        double successChanceLucky = getActivationChance(skillActivationType, subSkillType, player, true);
 | 
			
		||||
        //TODO: Most likely incorrectly displays the value for graceful roll but gonna ignore for now...
 | 
			
		||||
        successChance *= multiplier; //Currently only used for graceful roll
 | 
			
		||||
        String[] displayValues = new String[2];
 | 
			
		||||
 | 
			
		||||
        boolean isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
 | 
			
		||||
 | 
			
		||||
        displayValues[0] = percent.format(Math.min(successChance, 100.0D) / 100.0D);
 | 
			
		||||
        displayValues[1] = isLucky ? percent.format(Math.min(successChanceLucky, 100.0D) / 100.0D) : null;
 | 
			
		||||
 | 
			
		||||
        return displayValues;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double addLuck(@NotNull Player player, @NotNull PrimarySkillType primarySkillType, double chance) {
 | 
			
		||||
        if (Permissions.lucky(player, primarySkillType))
 | 
			
		||||
            return chance * LUCKY_MODIFIER;
 | 
			
		||||
        else
 | 
			
		||||
            return chance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double addLuck(boolean isLucky, double chance) {
 | 
			
		||||
        if (isLucky)
 | 
			
		||||
            return chance * LUCKY_MODIFIER;
 | 
			
		||||
        else
 | 
			
		||||
            return chance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double getMaximumProbability(@NotNull SubSkillType subSkillType) {
 | 
			
		||||
        return AdvancedConfig.getInstance().getMaximumProbability(subSkillType);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static double getMaxBonusLevelCap(@NotNull SubSkillType subSkillType) {
 | 
			
		||||
        return AdvancedConfig.getInstance().getMaxBonusLevel(subSkillType);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
package com.gmail.nossr50.util.random;
 | 
			
		||||
 | 
			
		||||
public enum SkillProbabilityType {
 | 
			
		||||
    DYNAMIC_CONFIGURABLE, //Has multiple values used for calculation (taken from config files)
 | 
			
		||||
    STATIC_CONFIGURABLE, //A single value used for calculations (taken from config files)
 | 
			
		||||
}
 | 
			
		||||
@@ -14,9 +14,11 @@ import com.gmail.nossr50.locale.LocaleLoader;
 | 
			
		||||
import com.gmail.nossr50.mcMMO;
 | 
			
		||||
import com.gmail.nossr50.util.ItemUtils;
 | 
			
		||||
import com.gmail.nossr50.util.Misc;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.compat.layers.persistentdata.AbstractPersistentDataLayer;
 | 
			
		||||
import com.gmail.nossr50.util.player.NotificationManager;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import com.gmail.nossr50.util.random.*;
 | 
			
		||||
import com.gmail.nossr50.util.text.StringUtils;
 | 
			
		||||
import org.bukkit.Bukkit;
 | 
			
		||||
import org.bukkit.Location;
 | 
			
		||||
@@ -334,4 +336,92 @@ public final class SkillUtils {
 | 
			
		||||
 | 
			
		||||
        return quantity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This is one of several Skill RNG check methods
 | 
			
		||||
     * This helper method is for specific {@link SubSkillType}, which help mcMMO understand where the RNG values used in our calculations come from from this {@link SubSkillType}
 | 
			
		||||
     *
 | 
			
		||||
     * 1) Determine where the RNG values come from for the passed {@link SubSkillType}
 | 
			
		||||
     *  NOTE: In the config file, there are values which are static and which are more dynamic, this is currently a bit hardcoded and will need to be updated manually
 | 
			
		||||
     *
 | 
			
		||||
     * 2) Determine whether or not to use Lucky multiplier and influence the outcome
 | 
			
		||||
     *
 | 
			
		||||
     * 3) Creates a {@link Probability} and pipes it to {@link RandomChanceUtil} which processes the result and returns it
 | 
			
		||||
     *
 | 
			
		||||
     * @param subSkillType target subskill
 | 
			
		||||
     * @param player target player, can be null (null players are given odds equivalent to a player with no levels or luck)
 | 
			
		||||
     * @return true if the Skill RNG succeeds, false if it fails
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isSkillRNGSuccessful(@NotNull SubSkillType subSkillType, @Nullable Player player) {
 | 
			
		||||
        try {
 | 
			
		||||
            //Process probability
 | 
			
		||||
            Probability probability = getSubSkillProbability(subSkillType, player);
 | 
			
		||||
            //Player can be null
 | 
			
		||||
            boolean isLucky = player != null && Permissions.lucky(player, subSkillType.getParentSkill());
 | 
			
		||||
 | 
			
		||||
            if(isLucky) {
 | 
			
		||||
                return RandomChanceUtil.processProbability(probability, RandomChanceUtil.LUCKY_MODIFIER);
 | 
			
		||||
            } else {
 | 
			
		||||
                return RandomChanceUtil.processProbability(probability);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } catch (RuntimeException | InvalidStaticChance e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This is one of several Skill RNG check methods
 | 
			
		||||
     * This helper method is specific to static value RNG, which can be influenced by a player's Luck
 | 
			
		||||
     *
 | 
			
		||||
     * @param primarySkillType the related primary skill
 | 
			
		||||
     * @param player the target player, can be null (null players have the worst odds)
 | 
			
		||||
     * @param probabilityPercentage the probability of this player succeeding in "percentage" format (0-100 inclusive)
 | 
			
		||||
     * @return true if the RNG succeeds, false if it fails
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isStaticSkillRNGSuccessful(@NotNull PrimarySkillType primarySkillType, @Nullable Player player, double probabilityPercentage) {
 | 
			
		||||
        //Grab a probability converted from a "percentage" value
 | 
			
		||||
        Probability probability = ProbabilityFactory.ofPercentageValue(probabilityPercentage);
 | 
			
		||||
 | 
			
		||||
        return isStaticSkillRNGSuccessful(primarySkillType, player, probability);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This is one of several Skill RNG check methods
 | 
			
		||||
     * This helper method is specific to static value RNG, which can be influenced by a player's Luck
 | 
			
		||||
     *
 | 
			
		||||
     * @param primarySkillType the related primary skill
 | 
			
		||||
     * @param player the target player, can be null (null players have the worst odds)
 | 
			
		||||
     * @param probability the probability of this player succeeding
 | 
			
		||||
     * @return true if the RNG succeeds, false if it fails
 | 
			
		||||
     */
 | 
			
		||||
    public static boolean isStaticSkillRNGSuccessful(@NotNull PrimarySkillType primarySkillType, @Nullable Player player, @NotNull Probability probability) {
 | 
			
		||||
        boolean isLucky = player != null && Permissions.lucky(player, primarySkillType);
 | 
			
		||||
 | 
			
		||||
        if(isLucky) {
 | 
			
		||||
            return RandomChanceUtil.processProbability(probability, RandomChanceUtil.LUCKY_MODIFIER);
 | 
			
		||||
        } else {
 | 
			
		||||
            return RandomChanceUtil.processProbability(probability);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Grab the {@link Probability} for a specific {@link SubSkillType} for a specific {@link Player}
 | 
			
		||||
     *
 | 
			
		||||
     * @param subSkillType target subskill
 | 
			
		||||
     * @param player target player
 | 
			
		||||
     * @return the Probability of this skill succeeding
 | 
			
		||||
     * @throws InvalidStaticChance when a skill that does not have a hard coded static chance and it is asked for
 | 
			
		||||
     * @throws RuntimeException
 | 
			
		||||
     */
 | 
			
		||||
    public static @NotNull Probability getSubSkillProbability(@NotNull SubSkillType subSkillType, @Nullable Player player) throws InvalidStaticChance, RuntimeException {
 | 
			
		||||
        SkillProbabilityType skillProbabilityType = SkillProbabilityType.DYNAMIC_CONFIGURABLE;
 | 
			
		||||
 | 
			
		||||
        if(subSkillType == SubSkillType.TAMING_FAST_FOOD_SERVICE || subSkillType == SubSkillType.AXES_ARMOR_IMPACT || subSkillType == SubSkillType.AXES_GREATER_IMPACT)
 | 
			
		||||
            skillProbabilityType = SkillProbabilityType.STATIC_CONFIGURABLE;
 | 
			
		||||
 | 
			
		||||
        return ProbabilityFactory.ofSubSkill(player, subSkillType, skillProbabilityType);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
////TODO: Rewrite the entire com.gmail.nossr50.util.random package, it was written in haste and it disgusts me
 | 
			
		||||
////TODO: Add more tests for the other types of random dice rolls
 | 
			
		||||
//@RunWith(PowerMockRunner.class)
 | 
			
		||||
//@PrepareForTest({RandomChanceUtil.class, UserManager.class})
 | 
			
		||||
//@PrepareForTest({RandomChanceUtil.class, UserManager.class, PrimarySkillType.class})
 | 
			
		||||
//public class RandomChanceTest {
 | 
			
		||||
//
 | 
			
		||||
//    private Player luckyPlayer;
 | 
			
		||||
@@ -37,12 +37,12 @@
 | 
			
		||||
//
 | 
			
		||||
//    @Before
 | 
			
		||||
//    public void setUpMock() {
 | 
			
		||||
//        primarySkillType = PrimarySkillType.HERBALISM;
 | 
			
		||||
//        subSkillType = SubSkillType.HERBALISM_GREEN_THUMB;
 | 
			
		||||
//        primarySkillType = PrimarySkillType.MINING;
 | 
			
		||||
//        subSkillType = SubSkillType.MINING_MOTHER_LODE;
 | 
			
		||||
//
 | 
			
		||||
//        //TODO: Likely needs to be changed per skill if more tests were added
 | 
			
		||||
//        PowerMockito.stub(PowerMockito.method(RandomChanceUtil.class, "getMaximumProbability", subSkillType.getClass())).toReturn(100D);
 | 
			
		||||
//        PowerMockito.stub(PowerMockito.method(RandomChanceUtil.class, "getMaxBonusLevelCap", subSkillType.getClass())).toReturn(1000D);
 | 
			
		||||
//        PowerMockito.stub(PowerMockito.method(RandomChanceUtil.class, "getMaximumProbability", subSkillType.getClass())).toReturn(10.0D);
 | 
			
		||||
//        PowerMockito.stub(PowerMockito.method(RandomChanceUtil.class, "getMaxBonusLevelCap", subSkillType.getClass())).toReturn(10000D);
 | 
			
		||||
//
 | 
			
		||||
//        normalPlayer = mock(Player.class);
 | 
			
		||||
//        luckyPlayer = mock(Player.class);
 | 
			
		||||
@@ -62,39 +62,39 @@
 | 
			
		||||
//        Mockito.when(Permissions.lucky(luckyPlayer, primarySkillType)).thenReturn(true);
 | 
			
		||||
//        Mockito.when(Permissions.lucky(normalPlayer, primarySkillType)).thenReturn(false);
 | 
			
		||||
//
 | 
			
		||||
//        Mockito.when(mmoPlayerNormal.getSkillLevel(primarySkillType)).thenReturn(800);
 | 
			
		||||
//        Mockito.when(mmoPlayerLucky.getSkillLevel(primarySkillType)).thenReturn(800);
 | 
			
		||||
//        Mockito.when(mmoPlayerNormal.getSkillLevel(primarySkillType)).thenReturn(2150);
 | 
			
		||||
//        Mockito.when(mmoPlayerLucky.getSkillLevel(primarySkillType)).thenReturn(2150);
 | 
			
		||||
//    }
 | 
			
		||||
//
 | 
			
		||||
//    @Test
 | 
			
		||||
//    public void testLuckyChance() {
 | 
			
		||||
//        System.out.println(testASCIIHeader);
 | 
			
		||||
//        System.out.println("Testing success odds to fall within expected values...");
 | 
			
		||||
//        assertEquals(80D, getSuccessChance(mmoPlayerNormal),0D);
 | 
			
		||||
//        assertEquals(80D * RandomChanceUtil.LUCKY_MODIFIER, getSuccessChance(mmoPlayerLucky),0D);
 | 
			
		||||
//        assertEquals(2.15D, getSuccessChance(mmoPlayerNormal),0.00D);
 | 
			
		||||
//        assertEquals(2.15D * RandomChanceUtil.LUCKY_MODIFIER, getSuccessChance(mmoPlayerLucky),0.00D);
 | 
			
		||||
//    }
 | 
			
		||||
//
 | 
			
		||||
//    @Test
 | 
			
		||||
//    public void testNeverFailsSuccessLuckyPlayer() {
 | 
			
		||||
//        System.out.println(testASCIIHeader);
 | 
			
		||||
//        System.out.println("Test - Lucky Player with 80% base success should never fail (10,000 iterations)");
 | 
			
		||||
//        for(int x = 0; x < 10000; x++) {
 | 
			
		||||
//            Assert.assertTrue(RandomChanceUtil.checkRandomChanceExecutionSuccess(luckyPlayer, SubSkillType.HERBALISM_GREEN_THUMB, true));
 | 
			
		||||
//            if(x == 10000-1)
 | 
			
		||||
//                System.out.println("They never failed!");
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
////    @Test
 | 
			
		||||
////    public void testNeverFailsSuccessLuckyPlayer() {
 | 
			
		||||
////        System.out.println(testASCIIHeader);
 | 
			
		||||
////        System.out.println("Test - Lucky Player with 80% base success should never fail (10,000 iterations)");
 | 
			
		||||
////        for(int x = 0; x < 10000; x++) {
 | 
			
		||||
////            Assert.assertTrue(RandomChanceUtil.checkRandomChanceExecutionSuccess(luckyPlayer, SubSkillType.HERBALISM_GREEN_THUMB, true));
 | 
			
		||||
////            if(x == 10000-1)
 | 
			
		||||
////                System.out.println("They never failed!");
 | 
			
		||||
////        }
 | 
			
		||||
////    }
 | 
			
		||||
//
 | 
			
		||||
//    @Test
 | 
			
		||||
//    public void testFailsAboutExpected() {
 | 
			
		||||
//        System.out.println(testASCIIHeader);
 | 
			
		||||
//        System.out.println("Test - Player with 800 skill should fail about 20% of the time (100,000 iterations)");
 | 
			
		||||
//        double ratioDivisor = 1000; //1000 because we run the test 100,000 times
 | 
			
		||||
//        double expectedFailRate = 20D;
 | 
			
		||||
//        double expectedFailRate = 100.0D - 2.15D;
 | 
			
		||||
//
 | 
			
		||||
//        double win = 0, loss = 0;
 | 
			
		||||
//        for(int x = 0; x < 100000; x++) {
 | 
			
		||||
//            if(RandomChanceUtil.checkRandomChanceExecutionSuccess(normalPlayer, SubSkillType.HERBALISM_GREEN_THUMB, true)) {
 | 
			
		||||
//            if(RandomChanceUtil.checkRandomChanceExecutionSuccess(normalPlayer, SubSkillType.MINING_MOTHER_LODE, true)) {
 | 
			
		||||
//                win++;
 | 
			
		||||
//            } else {
 | 
			
		||||
//                loss++;
 | 
			
		||||
@@ -102,7 +102,7 @@
 | 
			
		||||
//        }
 | 
			
		||||
//
 | 
			
		||||
//        double lossRatio = (loss / ratioDivisor);
 | 
			
		||||
//        Assert.assertEquals(lossRatio, expectedFailRate, 1D);
 | 
			
		||||
//        Assert.assertEquals(lossRatio, expectedFailRate, 0.01D);
 | 
			
		||||
//    }
 | 
			
		||||
//
 | 
			
		||||
//    private double getSuccessChance(@NotNull McMMOPlayer mmoPlayer) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user