mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2025-06-27 19:24:44 +02:00
Rewrote the RNG system to be more unified
This commit is contained in:
@ -0,0 +1,5 @@
|
||||
package com.gmail.nossr50.util.random;
|
||||
|
||||
public class InvalidActivationException extends Exception {
|
||||
//Weee
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.gmail.nossr50.util.random;
|
||||
|
||||
public class InvalidStaticChance extends Exception {
|
||||
//Weeee
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
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();
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
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.util.player.UserManager;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class RandomChanceSkill implements RandomChanceExecution {
|
||||
|
||||
protected final PrimarySkillType primarySkillType;
|
||||
protected final SubSkillType subSkillType;
|
||||
protected final double probabilityCap;
|
||||
private int skillLevel;
|
||||
|
||||
public RandomChanceSkill(Player player, SubSkillType subSkillType)
|
||||
{
|
||||
this.primarySkillType = subSkillType.getParentSkill();
|
||||
this.subSkillType = subSkillType;
|
||||
this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
|
||||
|
||||
if(player != null)
|
||||
this.skillLevel = UserManager.getPlayer(player).getSkillLevel(primarySkillType);
|
||||
else
|
||||
this.skillLevel = 0;
|
||||
}
|
||||
|
||||
public RandomChanceSkill(Player player, SubSkillType subSkillType, boolean hasCap)
|
||||
{
|
||||
if(hasCap)
|
||||
this.probabilityCap = AdvancedConfig.getInstance().getMaximumProbability(subSkillType);
|
||||
else
|
||||
this.probabilityCap = RandomChanceUtil.LINEAR_CURVE_VAR;
|
||||
|
||||
this.primarySkillType = subSkillType.getParentSkill();
|
||||
this.subSkillType = subSkillType;
|
||||
|
||||
if(player != null)
|
||||
this.skillLevel = UserManager.getPlayer(player).getSkillLevel(primarySkillType);
|
||||
else
|
||||
this.skillLevel = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The subskill corresponding to this RandomChanceSkill
|
||||
* @return this subskill
|
||||
*/
|
||||
public SubSkillType getSubSkill() {
|
||||
return 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 AdvancedConfig.getInstance().getMaxBonusLevel(subSkillType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.gmail.nossr50.util.random;
|
||||
|
||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class RandomChanceSkillStatic extends RandomChanceSkill {
|
||||
private final double xPos;
|
||||
|
||||
public RandomChanceSkillStatic(double xPos, Player player, SubSkillType subSkillType)
|
||||
{
|
||||
super(player, subSkillType);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.gmail.nossr50.util.random;
|
||||
|
||||
public class RandomChanceStatic implements RandomChanceExecution {
|
||||
private final double xPos;
|
||||
private final double probabilityCap;
|
||||
|
||||
public RandomChanceStatic(double xPos)
|
||||
{
|
||||
this.xPos = xPos;
|
||||
this.probabilityCap = 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,286 @@
|
||||
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.datatypes.skills.subskills.AbstractSubSkill;
|
||||
import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillEvent;
|
||||
import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillRandomCheckEvent;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.EventUtils;
|
||||
import com.gmail.nossr50.util.Misc;
|
||||
import com.gmail.nossr50.util.Permissions;
|
||||
import com.gmail.nossr50.util.skills.SkillActivationType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomChanceUtil
|
||||
{
|
||||
public static final DecimalFormat percent = new DecimalFormat("##0.00%");
|
||||
//public static final DecimalFormat decimal = new DecimalFormat("##0.00");
|
||||
public static final double LINEAR_CURVE_VAR = 100.0D;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @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 they event is not cancelled
|
||||
*/
|
||||
public static boolean isActivationSuccessful(SkillActivationType skillActivationType, SubSkillType subSkillType, 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(SkillActivationType skillActivationType, SubSkillType subSkillType, Player player)
|
||||
{
|
||||
switch(skillActivationType)
|
||||
{
|
||||
case RANDOM_LINEAR_100_SCALE_WITH_CAP:
|
||||
return getRandomChanceExecutionSuccess(player, subSkillType, true);
|
||||
case RANDOM_STATIC_CHANCE:
|
||||
return getRandomStaticChanceExecutionSuccess(player, subSkillType);
|
||||
default:
|
||||
return 0.1337;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not the random chance succeeds
|
||||
* @return true if the random chance succeeds
|
||||
*/
|
||||
public static boolean checkRandomChanceExecutionSuccess(double chance)
|
||||
{
|
||||
//Check the odds
|
||||
chance *= 100;
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
Random random = new Random();
|
||||
|
||||
if (chanceOfSuccess > random.nextInt(bound))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for stuff like Excavation, Fishing, etc...
|
||||
* @param randomChance
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkRandomChanceExecutionSuccess(RandomChanceSkillStatic randomChance)
|
||||
{
|
||||
double chanceOfSuccess = calculateChanceOfSuccess(randomChance);
|
||||
|
||||
//Check the odds
|
||||
return rollDice(chanceOfSuccess, 100);
|
||||
}
|
||||
|
||||
public static boolean checkRandomChanceExecutionSuccess(RandomChanceSkill randomChance)
|
||||
{
|
||||
double chanceOfSuccess = calculateChanceOfSuccess(randomChance);
|
||||
|
||||
Random random = new Random();
|
||||
|
||||
//Check the odds
|
||||
return rollDice(chanceOfSuccess, 100);
|
||||
}
|
||||
|
||||
|
||||
/*public static double getRandomChanceExecutionChance(RandomChanceSkill randomChance)
|
||||
{
|
||||
double chanceOfSuccess = calculateChanceOfSuccess(randomChance);
|
||||
return chanceOfSuccess;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Gets the Static Chance for something to activate
|
||||
* @param randomChance
|
||||
* @return
|
||||
*/
|
||||
public static double getRandomChanceExecutionChance(RandomChanceExecution randomChance) {
|
||||
double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap(), LINEAR_CURVE_VAR);
|
||||
return chanceOfSuccess;
|
||||
}
|
||||
|
||||
/*private static double calculateChanceOfSuccess(RandomChanceStatic randomChance) {
|
||||
double chanceOfSuccess = getChanceOfSuccess(randomChance.getXPos(), randomChance.getProbabilityCap());
|
||||
return chanceOfSuccess;
|
||||
}*/
|
||||
|
||||
private static double calculateChanceOfSuccess(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);
|
||||
}
|
||||
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 x, double y, double z)
|
||||
{
|
||||
//return (int) (x / (y / LINEAR_CURVE_VAR));
|
||||
return (int) (y * (x/z));
|
||||
// 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(Player player, SubSkillType subSkillType, boolean hasCap)
|
||||
{
|
||||
RandomChanceSkill rcs = new RandomChanceSkill(player, subSkillType, hasCap);
|
||||
return getRandomChanceExecutionChance(rcs);
|
||||
}
|
||||
|
||||
public static double getRandomStaticChanceExecutionSuccess(Player player, SubSkillType subSkillType)
|
||||
{
|
||||
try {
|
||||
return getRandomChanceExecutionChance(new RandomChanceSkillStatic(getStaticRandomChance(subSkillType), player, subSkillType));
|
||||
} catch (InvalidStaticChance invalidStaticChance) {
|
||||
//Catch invalid static skills
|
||||
invalidStaticChance.printStackTrace();
|
||||
}
|
||||
|
||||
return 0.1337; //Puts on shades
|
||||
}
|
||||
|
||||
public static boolean checkRandomChanceExecutionSuccess(Player player, SubSkillType subSkillType, boolean hasCap)
|
||||
{
|
||||
return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType, hasCap));
|
||||
}
|
||||
|
||||
public static boolean checkRandomChanceExecutionSuccess(Player player, SubSkillType subSkillType)
|
||||
{
|
||||
return checkRandomChanceExecutionSuccess(new RandomChanceSkill(player, subSkillType));
|
||||
}
|
||||
|
||||
public static boolean checkRandomStaticChanceExecutionSuccess(Player player, 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
|
||||
* @throws InvalidStaticChance if the skill has no defined static chance this exception will be thrown and you should know you're a naughty boy
|
||||
* @return The static activation roll involved in the RNG calculation
|
||||
*/
|
||||
public static double getStaticRandomChance(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();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean sendSkillEvent(Player player, SubSkillType subSkillType, double activationChance)
|
||||
{
|
||||
SubSkillRandomCheckEvent event = new SubSkillRandomCheckEvent(player, subSkillType, activationChance);
|
||||
return !event.isCancelled();
|
||||
}
|
||||
|
||||
/*public static boolean treasureDropSuccessful(Player player, double dropChance, int activationChance) {
|
||||
SubSkillRandomCheckEvent event = new SubSkillRandomCheckEvent(player, SubSkillType.EXCAVATION_ARCHAEOLOGY, dropChance / activationChance);
|
||||
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
||||
return (event.getChance() * activationChance) > (Misc.getRandom().nextDouble() * activationChance) && !event.isCancelled();
|
||||
}*/
|
||||
|
||||
public static boolean isActivationSuccessful(SkillActivationType skillActivationType, AbstractSubSkill abstractSubSkill, Player player)
|
||||
{
|
||||
return isActivationSuccessful(skillActivationType, abstractSubSkill.getSubSkillType(), player);
|
||||
}
|
||||
|
||||
public static String[] calculateAbilityDisplayValues(SkillActivationType skillActivationType, Player player, SubSkillType subSkillType) {
|
||||
double successChance = getActivationChance(skillActivationType, subSkillType, player);
|
||||
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(successChance * 1.3333D, 100.0D) / 100.0D) : null;
|
||||
|
||||
return displayValues;
|
||||
}
|
||||
|
||||
public static String[] calculateAbilityDisplayValuesStatic(Player player, PrimarySkillType primarySkillType, double chance) {
|
||||
RandomChanceStatic rcs = new RandomChanceStatic(chance);
|
||||
double successChance = getRandomChanceExecutionChance(rcs);
|
||||
|
||||
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 * 1.3333D, 100.0D) / 100.0D) : null;
|
||||
|
||||
return displayValues;
|
||||
}
|
||||
|
||||
public static String[] calculateAbilityDisplayValuesCustom(SkillActivationType skillActivationType, Player player, SubSkillType subSkillType, double multiplier) {
|
||||
double successChance = getActivationChance(skillActivationType, subSkillType, player);
|
||||
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(successChance * 1.3333D, 100.0D) / 100.0D) : null;
|
||||
|
||||
return displayValues;
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ package com.gmail.nossr50.util.skills;
|
||||
* Defines the type of random calculations to use with a given skill
|
||||
*/
|
||||
public enum SkillActivationType {
|
||||
RANDOM_LINEAR_100_SCALE_NO_CAP, //A skill level of 100 would guarantee the proc with this
|
||||
//RANDOM_LINEAR_100_SCALE_NO_CAP, //A skill level of 100 would guarantee the proc with this
|
||||
RANDOM_LINEAR_100_SCALE_WITH_CAP, //This one is based on a scale of 1-100 but with a specified cap for max bonus
|
||||
RANDOM_STATIC_CHANCE, //The skill always has a SPECIFIC chance to succeed
|
||||
ALWAYS_FIRES //This skill isn't chance based and always fires
|
||||
|
@ -9,13 +9,8 @@ import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
||||
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
|
||||
import com.gmail.nossr50.datatypes.skills.XPGainReason;
|
||||
import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill;
|
||||
import com.gmail.nossr50.datatypes.skills.subskills.interfaces.RandomChance;
|
||||
import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillEvent;
|
||||
import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillWeightedActivationCheckEvent;
|
||||
import com.gmail.nossr50.locale.LocaleLoader;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.EventUtils;
|
||||
import com.gmail.nossr50.util.ItemUtils;
|
||||
import com.gmail.nossr50.util.Misc;
|
||||
import com.gmail.nossr50.util.StringUtils;
|
||||
@ -33,15 +28,11 @@ import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SkillUtils {
|
||||
|
||||
public static final DecimalFormat percent = new DecimalFormat("##0.00%");
|
||||
public static final DecimalFormat decimal = new DecimalFormat("##0.00");
|
||||
|
||||
public static void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason) {
|
||||
mcMMOPlayer.beginXpGain(skill, xp, xpGainReason);
|
||||
}
|
||||
@ -50,25 +41,6 @@ public class SkillUtils {
|
||||
* Skill Stat Calculations
|
||||
*/
|
||||
|
||||
public static String[] calculateAbilityDisplayValues(double chance, boolean isLucky) {
|
||||
String[] displayValues = new String[2];
|
||||
|
||||
displayValues[0] = percent.format(Math.min(chance, 100.0D) / 100.0D);
|
||||
displayValues[1] = isLucky ? percent.format(Math.min(chance * 1.3333D, 100.0D) / 100.0D) : null;
|
||||
|
||||
return displayValues;
|
||||
}
|
||||
|
||||
public static String[] calculateAbilityDisplayValues(float skillValue, SubSkillType subSkillType, boolean isLucky) {
|
||||
int maxBonusLevel = AdvancedConfig.getInstance().getMaxBonusLevel(subSkillType);
|
||||
|
||||
return calculateAbilityDisplayValues((AdvancedConfig.getInstance().getMaxChance(subSkillType) / maxBonusLevel) * Math.min(skillValue, maxBonusLevel), isLucky);
|
||||
}
|
||||
|
||||
public static String[] calculateAbilityDisplayValuesCustom(float skillValue, boolean isLucky, int maxBonusLevel, double maxChance) {
|
||||
return calculateAbilityDisplayValues((maxChance / maxBonusLevel) * Math.min(skillValue, maxBonusLevel), isLucky);
|
||||
}
|
||||
|
||||
public static String[] calculateLengthDisplayValues(Player player, float skillValue, PrimarySkillType skill) {
|
||||
int maxLength = skill.getAbility().getMaxLength();
|
||||
int abilityLengthVar = AdvancedConfig.getInstance().getAbilityLength();
|
||||
@ -270,213 +242,6 @@ public class SkillUtils {
|
||||
itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not the given skill succeeds
|
||||
* @param subSkillType The ability corresponding to this check
|
||||
* @param player The player whose skill levels we are checking against
|
||||
* @param skillLevel The skill level of the corresponding skill
|
||||
* @param activationChance used to determine activation chance
|
||||
* @param maxChance maximum chance
|
||||
* @param maxLevel maximum skill level bonus
|
||||
* @return true if random chance succeeds and the event isn't cancelled
|
||||
*/
|
||||
private static boolean performRandomSkillCheck(SubSkillType subSkillType, Player player, int skillLevel, int activationChance, double maxChance, int maxLevel) {
|
||||
if(Config.getInstance().getIsRetroMode())
|
||||
maxLevel = maxLevel * 10;
|
||||
|
||||
double chance = (maxChance / maxLevel) * Math.min(skillLevel, maxLevel) / activationChance;
|
||||
return performRandomSkillCheckStatic(subSkillType, player, activationChance, chance);
|
||||
}
|
||||
|
||||
/* NEW VERSION */
|
||||
private static boolean performRandomSkillCheck(AbstractSubSkill abstractSubSkill, Player player, int skillLevel, int activationChance, double maxChance, int maxLevel) {
|
||||
if(Config.getInstance().getIsRetroMode())
|
||||
maxLevel = maxLevel * 10;
|
||||
|
||||
double chance = (maxChance / maxLevel) * Math.min(skillLevel, maxLevel) / activationChance;
|
||||
return performRandomSkillCheckStatic(abstractSubSkill, player, activationChance, chance);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is the final step in determining if a Sub-Skill / Secondary Skill in mcMMO successfully activates either from chance or otherwise
|
||||
*
|
||||
* There are 4 types of Sub-Skill / Secondary Skill activations in mcMMO
|
||||
* 1) Random Chance with a linear increase to 100% (At 100 Skill Level)
|
||||
* 2) Random Chance with a linear increase to 100% at 100 Skill Level but caps out earlier in the curve (At x/100 Skill Level)
|
||||
* 3) Random Chance with a pre-determined activation roll and threshold roll
|
||||
* 4) Skills that are not chance based
|
||||
*
|
||||
* Random skills check for success based on numbers and then fire a cancellable event, if that event is not cancelled they succeed
|
||||
* All other skills just fire the cancellable event and succeed if it is not cancelled
|
||||
*
|
||||
* @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
|
||||
* @param activationChance This is the value that we roll against, 100 is normal, and 75 is for lucky perk
|
||||
* @return returns true if all conditions are met and they event is not cancelled
|
||||
*/
|
||||
public static boolean isActivationSuccessful(SkillActivationType skillActivationType, SubSkillType subSkillType, Player player,
|
||||
int skillLevel, int activationChance)
|
||||
{
|
||||
//Maximum chance to succeed
|
||||
double maxChance = AdvancedConfig.getInstance().getMaxChance(subSkillType);
|
||||
//Maximum roll we can make
|
||||
int maxBonusLevel = AdvancedConfig.getInstance().getMaxBonusLevel(subSkillType);
|
||||
|
||||
switch(skillActivationType)
|
||||
{
|
||||
//100 Skill = Guaranteed
|
||||
case RANDOM_LINEAR_100_SCALE_NO_CAP:
|
||||
return performRandomSkillCheck(subSkillType, player, skillLevel, PerksUtils.handleLuckyPerks(player, subSkillType.getParentSkill()), 100.0D, 100);
|
||||
case RANDOM_LINEAR_100_SCALE_WITH_CAP:
|
||||
return performRandomSkillCheck(subSkillType, player, skillLevel, PerksUtils.handleLuckyPerks(player, subSkillType.getParentSkill()), maxChance, maxBonusLevel);
|
||||
case RANDOM_STATIC_CHANCE:
|
||||
//Grab the static activation chance of this skill
|
||||
double staticRoll = getSecondaryAbilityStaticChance(subSkillType) / activationChance;
|
||||
return performRandomSkillCheckStatic(subSkillType, player, activationChance, staticRoll);
|
||||
case ALWAYS_FIRES:
|
||||
SubSkillEvent event = EventUtils.callSubSkillEvent(player, subSkillType);
|
||||
return !event.isCancelled();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is for running a random success check with custom maxChance and maxBonusLevel values
|
||||
* Mostly used for RNG effects that can't be directly associated with a specific AbstractSubSkill
|
||||
* @param player target player
|
||||
* @param abstractSubSkill this abstract subskill
|
||||
* @param maxChance custom max chance
|
||||
* @param maxBonusLevel custom max bonus level
|
||||
* @return true if activation was successful
|
||||
*/
|
||||
public static boolean isActivationSuccessfulCustom(Player player, AbstractSubSkill abstractSubSkill, double maxChance, int maxBonusLevel)
|
||||
{
|
||||
int skillLevel = UserManager.getPlayer(player).getSkillLevel(abstractSubSkill.getPrimarySkill());
|
||||
|
||||
return performRandomSkillCheck(abstractSubSkill, player, skillLevel, PerksUtils.handleLuckyPerks(player, abstractSubSkill.getPrimarySkill()), maxChance, maxBonusLevel);
|
||||
}
|
||||
|
||||
public static double getChanceOfSuccess(int skillLevel, double maxLevelBonus, double curve)
|
||||
{
|
||||
return getChanceOfSuccess((double) skillLevel, maxLevelBonus, curve);
|
||||
}
|
||||
|
||||
public static double getChanceOfSuccess(double skillLevel, double maxLevelBonus, double curve)
|
||||
{
|
||||
if(skillLevel > maxLevelBonus)
|
||||
return maxLevelBonus / curve;
|
||||
|
||||
return skillLevel / curve;
|
||||
}
|
||||
|
||||
/* NEW VERSION */
|
||||
public static boolean isActivationSuccessful(SkillActivationType skillActivationType, AbstractSubSkill abstractSubSkill, Player player, double maxChance, int maxBonusLevel)
|
||||
{
|
||||
int skillLevel = UserManager.getPlayer(player).getSkillLevel(abstractSubSkill.getPrimarySkill());
|
||||
PrimarySkillType skill = abstractSubSkill.getPrimarySkill();
|
||||
|
||||
switch(skillActivationType)
|
||||
{
|
||||
//100 Skill = Guaranteed
|
||||
case RANDOM_LINEAR_100_SCALE_NO_CAP:
|
||||
return performRandomSkillCheck(abstractSubSkill, player, skillLevel, PerksUtils.handleLuckyPerks(player, skill), 100.0D, 100);
|
||||
case RANDOM_LINEAR_100_SCALE_WITH_CAP:
|
||||
return performRandomSkillCheck(abstractSubSkill, player, skillLevel, PerksUtils.handleLuckyPerks(player, skill), maxChance, maxBonusLevel);
|
||||
case RANDOM_STATIC_CHANCE:
|
||||
//TODO: Add this in for the new system
|
||||
//Grab the static activation chance of this skill
|
||||
//double staticRoll = getSecondaryAbilityStaticChance(subSkillType) / activationChance;
|
||||
//return performRandomSkillCheckStatic(subSkillType, player, activationChance, staticRoll);
|
||||
return false;
|
||||
case ALWAYS_FIRES:
|
||||
SubSkillEvent event = EventUtils.callSubSkillEvent(player, abstractSubSkill);
|
||||
return !event.isCancelled();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isActivationSuccessful(SkillActivationType skillActivationType, AbstractSubSkill abstractSubSkill, Player player)
|
||||
{
|
||||
//Maximum chance to succeed
|
||||
RandomChance randomChance = (RandomChance) abstractSubSkill;
|
||||
double maxChance = randomChance.getRandomChanceMaxChance();
|
||||
|
||||
//Maximum roll we can make
|
||||
int maxBonusLevel = randomChance.getRandomChanceMaxBonus();
|
||||
int skillLevel = UserManager.getPlayer(player).getSkillLevel(abstractSubSkill.getPrimarySkill());
|
||||
PrimarySkillType skill = abstractSubSkill.getPrimarySkill();
|
||||
|
||||
switch(skillActivationType)
|
||||
{
|
||||
//100 Skill = Guaranteed
|
||||
case RANDOM_LINEAR_100_SCALE_NO_CAP:
|
||||
return performRandomSkillCheck(abstractSubSkill, player, skillLevel, PerksUtils.handleLuckyPerks(player, skill), 100.0D, 100);
|
||||
case RANDOM_LINEAR_100_SCALE_WITH_CAP:
|
||||
return performRandomSkillCheck(abstractSubSkill, player, skillLevel, PerksUtils.handleLuckyPerks(player, skill), maxChance, maxBonusLevel);
|
||||
case RANDOM_STATIC_CHANCE:
|
||||
//TODO: Add this in for the new system
|
||||
//Grab the static activation chance of this skill
|
||||
//double staticRoll = getSecondaryAbilityStaticChance(subSkillType) / activationChance;
|
||||
//return performRandomSkillCheckStatic(subSkillType, player, activationChance, staticRoll);
|
||||
return false;
|
||||
case ALWAYS_FIRES:
|
||||
SubSkillEvent event = EventUtils.callSubSkillEvent(player, abstractSubSkill);
|
||||
return !event.isCancelled();
|
||||
default:
|
||||
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
|
||||
*/
|
||||
public static double getSecondaryAbilityStaticChance(SubSkillType subSkillType)
|
||||
{
|
||||
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:
|
||||
return 100.0D;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine whether or not a sub-skill activates from random chance (using static values)
|
||||
* @param subSkillType The identifier for this specific sub-skill
|
||||
* @param player The owner of this sub-skill
|
||||
* @param activationChance This is the value that we roll against, 100 is normal, and 75 is for lucky perk
|
||||
* @param chance This is the static modifier for our random calculations
|
||||
* @return true if random chance was successful and the event wasn't cancelled
|
||||
*/
|
||||
private static boolean performRandomSkillCheckStatic(SubSkillType subSkillType, Player player, int activationChance, double chance) {
|
||||
SubSkillWeightedActivationCheckEvent event = new SubSkillWeightedActivationCheckEvent(player, subSkillType, chance);
|
||||
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
||||
return (event.getChance() * activationChance) > Misc.getRandom().nextInt(activationChance) && !event.isCancelled();
|
||||
}
|
||||
|
||||
/* NEW VERSION */
|
||||
private static boolean performRandomSkillCheckStatic(AbstractSubSkill abstractSubSkill, Player player, int activationChance, double chance) {
|
||||
SubSkillWeightedActivationCheckEvent event = new SubSkillWeightedActivationCheckEvent(player, abstractSubSkill, chance);
|
||||
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
||||
return (event.getChance() * activationChance) > Misc.getRandom().nextInt(activationChance) && !event.isCancelled();
|
||||
}
|
||||
|
||||
public static boolean treasureDropSuccessful(Player player, double dropChance, int activationChance) {
|
||||
SubSkillWeightedActivationCheckEvent event = new SubSkillWeightedActivationCheckEvent(player, SubSkillType.EXCAVATION_ARCHAEOLOGY, dropChance / activationChance);
|
||||
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
||||
return (event.getChance() * activationChance) > (Misc.getRandom().nextDouble() * activationChance) && !event.isCancelled();
|
||||
}
|
||||
|
||||
private static boolean isLocalizedSkill(String skillName) {
|
||||
for (PrimarySkillType skill : PrimarySkillType.values()) {
|
||||
if (skillName.equalsIgnoreCase(LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".SkillName"))) {
|
||||
|
Reference in New Issue
Block a user