2013-03-01 06:52:01 +01:00
|
|
|
package com.gmail.nossr50.util.skills;
|
|
|
|
|
|
|
|
import com.gmail.nossr50.config.AdvancedConfig;
|
|
|
|
import com.gmail.nossr50.config.Config;
|
|
|
|
import com.gmail.nossr50.config.HiddenConfig;
|
2019-01-11 16:11:17 +01:00
|
|
|
import com.gmail.nossr50.datatypes.interactions.NotificationType;
|
2013-03-03 17:06:05 +01:00
|
|
|
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
2019-01-13 08:54:53 +01:00
|
|
|
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
2019-01-09 04:52:52 +01:00
|
|
|
import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
2019-01-13 04:56:54 +01:00
|
|
|
import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
|
2019-01-09 04:52:52 +01:00
|
|
|
import com.gmail.nossr50.datatypes.skills.XPGainReason;
|
|
|
|
import com.gmail.nossr50.datatypes.skills.subskills.AbstractSubSkill;
|
|
|
|
import com.gmail.nossr50.datatypes.skills.subskills.interfaces.RandomChance;
|
2018-12-29 14:24:55 +01:00
|
|
|
import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillEvent;
|
|
|
|
import com.gmail.nossr50.events.skills.secondaryabilities.SubSkillWeightedActivationCheckEvent;
|
2013-03-01 06:52:01 +01:00
|
|
|
import com.gmail.nossr50.locale.LocaleLoader;
|
2018-07-24 04:13:57 +02:00
|
|
|
import com.gmail.nossr50.mcMMO;
|
2014-05-11 14:58:08 +02:00
|
|
|
import com.gmail.nossr50.util.EventUtils;
|
2013-03-01 06:52:01 +01:00
|
|
|
import com.gmail.nossr50.util.ItemUtils;
|
|
|
|
import com.gmail.nossr50.util.Misc;
|
|
|
|
import com.gmail.nossr50.util.StringUtils;
|
2019-01-13 04:56:54 +01:00
|
|
|
import com.gmail.nossr50.util.player.NotificationManager;
|
2013-03-01 06:52:01 +01:00
|
|
|
import com.gmail.nossr50.util.player.UserManager;
|
2018-07-24 04:13:57 +02:00
|
|
|
import org.bukkit.Location;
|
|
|
|
import org.bukkit.Material;
|
|
|
|
import org.bukkit.enchantments.Enchantment;
|
|
|
|
import org.bukkit.entity.Player;
|
|
|
|
import org.bukkit.inventory.ItemStack;
|
|
|
|
import org.bukkit.inventory.Recipe;
|
|
|
|
import org.bukkit.inventory.ShapedRecipe;
|
|
|
|
import org.bukkit.inventory.ShapelessRecipe;
|
|
|
|
import org.bukkit.inventory.meta.ItemMeta;
|
|
|
|
import org.bukkit.potion.PotionEffect;
|
|
|
|
import org.bukkit.potion.PotionEffectType;
|
|
|
|
|
2019-01-09 04:52:52 +01:00
|
|
|
import java.text.DecimalFormat;
|
2018-07-24 04:13:57 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
2013-03-01 06:52:01 +01:00
|
|
|
|
|
|
|
public class SkillUtils {
|
2019-01-09 04:52:52 +01:00
|
|
|
|
|
|
|
public static final DecimalFormat percent = new DecimalFormat("##0.00%");
|
|
|
|
public static final DecimalFormat decimal = new DecimalFormat("##0.00");
|
|
|
|
|
2019-01-13 08:54:53 +01:00
|
|
|
public static void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason) {
|
2019-01-09 04:52:52 +01:00
|
|
|
mcMMOPlayer.beginXpGain(skill, xp, xpGainReason);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2019-01-15 03:35:37 +01:00
|
|
|
public static String[] calculateAbilityDisplayValuesCustom(float skillValue, SubSkillType subSkillType, boolean isLucky, int maxBonusLevel, double maxChance) {
|
|
|
|
return calculateAbilityDisplayValues((maxChance / maxBonusLevel) * Math.min(skillValue, maxBonusLevel), isLucky);
|
|
|
|
}
|
|
|
|
|
2019-01-13 08:54:53 +01:00
|
|
|
public static String[] calculateLengthDisplayValues(Player player, float skillValue, PrimarySkillType skill) {
|
2019-01-09 04:52:52 +01:00
|
|
|
int maxLength = skill.getAbility().getMaxLength();
|
2019-01-13 09:31:58 +01:00
|
|
|
int abilityLengthVar = Config.getInstance().getIsRetroMode() ? AdvancedConfig.getInstance().getAbilityLengthRetro() : AdvancedConfig.getInstance().getAbilityLengthStandard();
|
|
|
|
int length = 2 + (int) (skillValue / abilityLengthVar);
|
2019-01-09 04:52:52 +01:00
|
|
|
int enduranceLength = PerksUtils.handleActivationPerks(player, length, maxLength);
|
|
|
|
|
|
|
|
if (maxLength != 0) {
|
|
|
|
length = Math.min(length, maxLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new String[] { String.valueOf(length), String.valueOf(enduranceLength) };
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Others
|
|
|
|
*/
|
|
|
|
|
2019-01-15 14:35:41 +01:00
|
|
|
public static int handleFoodSkills(Player player, int eventFoodLevel, SubSkillType subSkillType) {
|
|
|
|
int curRank = RankUtils.getRank(player, subSkillType);
|
2013-03-01 06:52:01 +01:00
|
|
|
|
|
|
|
int currentFoodLevel = player.getFoodLevel();
|
|
|
|
int foodChange = eventFoodLevel - currentFoodLevel;
|
|
|
|
|
2019-01-15 14:35:41 +01:00
|
|
|
foodChange+=curRank;
|
2013-03-01 06:52:01 +01:00
|
|
|
|
|
|
|
return currentFoodLevel + foodChange;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Calculate the time remaining until the cooldown expires.
|
|
|
|
*
|
|
|
|
* @param deactivatedTimeStamp Time of deactivation
|
|
|
|
* @param cooldown The length of the cooldown
|
2013-09-22 22:58:12 +02:00
|
|
|
* @param player The Player to check for cooldown perks
|
|
|
|
*
|
2013-03-01 06:52:01 +01:00
|
|
|
* @return the number of seconds remaining before the cooldown expires
|
|
|
|
*/
|
|
|
|
public static int calculateTimeLeft(long deactivatedTimeStamp, int cooldown, Player player) {
|
|
|
|
return (int) (((deactivatedTimeStamp + (PerksUtils.handleCooldownPerks(player, cooldown) * Misc.TIME_CONVERSION_FACTOR)) - System.currentTimeMillis()) / Misc.TIME_CONVERSION_FACTOR);
|
|
|
|
}
|
|
|
|
|
2013-09-22 22:58:12 +02:00
|
|
|
/**
|
|
|
|
* Check if the cooldown has expired.
|
|
|
|
* This does NOT account for cooldown perks!
|
|
|
|
*
|
|
|
|
* @param deactivatedTimeStamp Time of deactivation in seconds
|
|
|
|
* @param cooldown The length of the cooldown in seconds
|
|
|
|
*
|
|
|
|
* @return true if the cooldown is expired
|
|
|
|
*/
|
|
|
|
public static boolean cooldownExpired(long deactivatedTimeStamp, int cooldown) {
|
2013-10-15 19:03:33 +02:00
|
|
|
return System.currentTimeMillis() >= (deactivatedTimeStamp + cooldown) * Misc.TIME_CONVERSION_FACTOR;
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if the given string represents a valid skill
|
|
|
|
*
|
|
|
|
* @param skillName The name of the skill to check
|
|
|
|
* @return true if this is a valid skill, false otherwise
|
|
|
|
*/
|
|
|
|
public static boolean isSkill(String skillName) {
|
2019-01-13 08:54:53 +01:00
|
|
|
return Config.getInstance().getLocale().equalsIgnoreCase("en_US") ? PrimarySkillType.getSkill(skillName) != null : isLocalizedSkill(skillName);
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
|
|
|
|
2019-01-11 16:11:17 +01:00
|
|
|
public static void sendSkillMessage(Player player, NotificationType notificationType, String key) {
|
2013-10-15 19:03:33 +02:00
|
|
|
Location location = player.getLocation();
|
|
|
|
|
2013-03-01 06:52:01 +01:00
|
|
|
for (Player otherPlayer : player.getWorld().getPlayers()) {
|
2013-10-15 19:03:33 +02:00
|
|
|
if (otherPlayer != player && Misc.isNear(location, otherPlayer.getLocation(), Misc.SKILL_MESSAGE_MAX_SENDING_DISTANCE)) {
|
2019-01-13 06:51:31 +01:00
|
|
|
NotificationManager.sendNearbyPlayersInformation(player, notificationType, key);
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void handleAbilitySpeedIncrease(Player player) {
|
|
|
|
if (HiddenConfig.getInstance().useEnchantmentBuffs()) {
|
2016-03-11 15:20:23 +01:00
|
|
|
ItemStack heldItem = player.getInventory().getItemInMainHand();
|
2013-03-01 06:52:01 +01:00
|
|
|
|
|
|
|
if (heldItem == null || heldItem.getType() == Material.AIR) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int efficiencyLevel = heldItem.getEnchantmentLevel(Enchantment.DIG_SPEED);
|
|
|
|
ItemMeta itemMeta = heldItem.getItemMeta();
|
|
|
|
List<String> itemLore = new ArrayList<String>();
|
|
|
|
|
|
|
|
if (itemMeta.hasLore()) {
|
|
|
|
itemLore = itemMeta.getLore();
|
|
|
|
}
|
|
|
|
|
|
|
|
itemLore.add("mcMMO Ability Tool");
|
2013-05-15 04:58:36 +02:00
|
|
|
itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel + AdvancedConfig.getInstance().getEnchantBuff(), true);
|
2013-03-01 06:52:01 +01:00
|
|
|
|
|
|
|
itemMeta.setLore(itemLore);
|
|
|
|
heldItem.setItemMeta(itemMeta);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int duration = 0;
|
|
|
|
int amplifier = 0;
|
|
|
|
|
|
|
|
if (player.hasPotionEffect(PotionEffectType.FAST_DIGGING)) {
|
|
|
|
for (PotionEffect effect : player.getActivePotionEffects()) {
|
|
|
|
if (effect.getType() == PotionEffectType.FAST_DIGGING) {
|
|
|
|
duration = effect.getDuration();
|
|
|
|
amplifier = effect.getAmplifier();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-03 17:06:05 +01:00
|
|
|
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
|
2019-01-13 08:54:53 +01:00
|
|
|
PrimarySkillType skill = mcMMOPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER) ? PrimarySkillType.MINING : PrimarySkillType.EXCAVATION;
|
2019-01-13 09:31:58 +01:00
|
|
|
int abilityLengthVar = Config.getInstance().getIsRetroMode() ? AdvancedConfig.getInstance().getAbilityLengthRetro() : AdvancedConfig.getInstance().getAbilityLengthStandard();
|
|
|
|
int ticks = PerksUtils.handleActivationPerks(player, 2 + (mcMMOPlayer.getSkillLevel(skill) / abilityLengthVar), skill.getAbility().getMaxLength()) * Misc.TICK_CONVERSION_FACTOR;
|
2013-03-01 06:52:01 +01:00
|
|
|
|
|
|
|
PotionEffect abilityBuff = new PotionEffect(PotionEffectType.FAST_DIGGING, duration + ticks, amplifier + 10);
|
|
|
|
player.addPotionEffect(abilityBuff, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void handleAbilitySpeedDecrease(Player player) {
|
2013-10-15 19:03:33 +02:00
|
|
|
if (!HiddenConfig.getInstance().useEnchantmentBuffs()) {
|
|
|
|
return;
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
|
|
|
|
2013-10-15 19:03:33 +02:00
|
|
|
for (ItemStack item : player.getInventory().getContents()) {
|
|
|
|
removeAbilityBuff(item);
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
2013-10-15 19:03:33 +02:00
|
|
|
}
|
2013-03-01 06:52:01 +01:00
|
|
|
|
2013-10-15 19:03:33 +02:00
|
|
|
public static void removeAbilityBuff(ItemStack item) {
|
|
|
|
if (item == null || item.getType() == Material.AIR || (!ItemUtils.isPickaxe(item) && !ItemUtils.isShovel(item)) || !item.containsEnchantment(Enchantment.DIG_SPEED)) {
|
|
|
|
return;
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
|
|
|
|
2013-10-15 19:03:33 +02:00
|
|
|
ItemMeta itemMeta = item.getItemMeta();
|
2013-03-01 06:52:01 +01:00
|
|
|
|
2013-10-15 19:03:33 +02:00
|
|
|
if (itemMeta.hasLore()) {
|
|
|
|
List<String> itemLore = itemMeta.getLore();
|
2013-03-01 06:52:01 +01:00
|
|
|
|
2013-10-15 19:03:33 +02:00
|
|
|
if (itemLore.remove("mcMMO Ability Tool")) {
|
|
|
|
int efficiencyLevel = item.getEnchantmentLevel(Enchantment.DIG_SPEED);
|
2013-03-01 06:52:01 +01:00
|
|
|
|
2013-10-15 19:03:33 +02:00
|
|
|
if (efficiencyLevel <= AdvancedConfig.getInstance().getEnchantBuff()) {
|
|
|
|
itemMeta.removeEnchant(Enchantment.DIG_SPEED);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel - AdvancedConfig.getInstance().getEnchantBuff(), true);
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
2013-10-15 19:03:33 +02:00
|
|
|
|
|
|
|
itemMeta.setLore(itemLore);
|
|
|
|
item.setItemMeta(itemMeta);
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-06 14:45:20 +01:00
|
|
|
public static void handleDurabilityChange(ItemStack itemStack, int durabilityModifier) {
|
|
|
|
handleDurabilityChange(itemStack, durabilityModifier, 1.0);
|
2013-11-05 14:51:45 +01:00
|
|
|
}
|
|
|
|
|
2013-08-09 22:21:45 +02:00
|
|
|
/**
|
|
|
|
* Modify the durability of an ItemStack.
|
|
|
|
*
|
|
|
|
* @param itemStack The ItemStack which durability should be modified
|
2013-11-06 14:45:20 +01:00
|
|
|
* @param durabilityModifier the amount to modify the durability by
|
|
|
|
* @param maxDamageModifier the amount to adjust the max damage by
|
2013-08-09 22:21:45 +02:00
|
|
|
*/
|
2013-11-06 14:45:20 +01:00
|
|
|
public static void handleDurabilityChange(ItemStack itemStack, int durabilityModifier, double maxDamageModifier) {
|
2018-02-15 22:59:10 +01:00
|
|
|
if (itemStack.hasItemMeta() && itemStack.getItemMeta().isUnbreakable()) {
|
2018-02-15 22:38:10 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-11-06 14:45:20 +01:00
|
|
|
Material type = itemStack.getType();
|
|
|
|
short maxDurability = mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability();
|
2013-11-06 20:52:19 +01:00
|
|
|
durabilityModifier = (int) Math.min(durabilityModifier / (itemStack.getEnchantmentLevel(Enchantment.DURABILITY) + 1), maxDurability * maxDamageModifier);
|
2013-11-06 14:45:20 +01:00
|
|
|
|
|
|
|
itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
|
|
|
|
2018-12-27 12:04:55 +01:00
|
|
|
/**
|
|
|
|
* Checks whether or not the given skill succeeds
|
2019-01-09 04:52:52 +01:00
|
|
|
* @param subSkillType The ability corresponding to this check
|
2018-12-27 12:04:55 +01:00
|
|
|
* @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
|
|
|
|
*/
|
2019-01-09 04:52:52 +01:00
|
|
|
private static boolean performRandomSkillCheck(SubSkillType subSkillType, Player player, int skillLevel, int activationChance, double maxChance, int maxLevel) {
|
|
|
|
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) {
|
2018-12-27 12:04:55 +01:00
|
|
|
double chance = (maxChance / maxLevel) * Math.min(skillLevel, maxLevel) / activationChance;
|
2019-01-09 04:52:52 +01:00
|
|
|
return performRandomSkillCheckStatic(abstractSubSkill, player, activationChance, chance);
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
|
|
|
|
2018-12-27 12:04:55 +01:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*
|
2019-01-09 04:52:52 +01:00
|
|
|
* @param subSkillType The identifier for this specific sub-skill
|
2018-12-27 12:04:55 +01:00
|
|
|
* @param player The owner of this sub-skill
|
|
|
|
* @param skill The identifier for the parent of our sub-skill
|
|
|
|
* @param activationChance This is the value that we roll against, 100 is normal, and 75 is for lucky perk
|
2019-01-15 03:35:37 +01:00
|
|
|
* @param skillActivationType this value represents what kind of activation procedures this sub-skill uses
|
2018-12-27 12:04:55 +01:00
|
|
|
* @return returns true if all conditions are met and they event is not cancelled
|
|
|
|
*/
|
2019-01-15 03:35:37 +01:00
|
|
|
public static boolean isActivationSuccessful(SkillActivationType skillActivationType, SubSkillType subSkillType, Player player,
|
2019-01-13 08:54:53 +01:00
|
|
|
PrimarySkillType skill, int skillLevel, int activationChance)
|
2018-12-27 12:04:55 +01:00
|
|
|
{
|
|
|
|
//Maximum chance to succeed
|
2019-01-09 04:52:52 +01:00
|
|
|
double maxChance = AdvancedConfig.getInstance().getMaxChance(subSkillType);
|
2018-12-27 12:04:55 +01:00
|
|
|
//Maximum roll we can make
|
2019-01-09 04:52:52 +01:00
|
|
|
int maxBonusLevel = AdvancedConfig.getInstance().getMaxBonusLevel(subSkillType);
|
2018-12-27 12:04:55 +01:00
|
|
|
|
2019-01-15 03:35:37 +01:00
|
|
|
switch(skillActivationType)
|
2018-12-27 12:04:55 +01:00
|
|
|
{
|
|
|
|
//100 Skill = Guaranteed
|
|
|
|
case RANDOM_LINEAR_100_SCALE_NO_CAP:
|
2019-01-09 04:52:52 +01:00
|
|
|
return performRandomSkillCheck(subSkillType, player, skillLevel, PerksUtils.handleLuckyPerks(player, skill), 100.0D, 100);
|
2018-12-27 12:04:55 +01:00
|
|
|
case RANDOM_LINEAR_100_SCALE_WITH_CAP:
|
2019-01-09 04:52:52 +01:00
|
|
|
return performRandomSkillCheck(subSkillType, player, skillLevel, PerksUtils.handleLuckyPerks(player, skill), maxChance, maxBonusLevel);
|
2018-12-27 12:04:55 +01:00
|
|
|
case RANDOM_STATIC_CHANCE:
|
|
|
|
//Grab the static activation chance of this skill
|
2019-01-09 04:52:52 +01:00
|
|
|
double staticRoll = getSecondaryAbilityStaticChance(subSkillType) / activationChance;
|
|
|
|
return performRandomSkillCheckStatic(subSkillType, player, activationChance, staticRoll);
|
2018-12-27 12:04:55 +01:00
|
|
|
case ALWAYS_FIRES:
|
2019-01-09 04:52:52 +01:00
|
|
|
SubSkillEvent event = EventUtils.callSubSkillEvent(player, subSkillType);
|
2018-12-27 12:04:55 +01:00
|
|
|
return !event.isCancelled();
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
|
|
|
|
2019-01-15 03:35:37 +01:00
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2019-01-10 10:17:47 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-01-09 04:52:52 +01:00
|
|
|
/* NEW VERSION */
|
|
|
|
public static boolean isActivationSuccessful(SkillActivationType skillActivationType, AbstractSubSkill abstractSubSkill, Player player, double maxChance, int maxBonusLevel)
|
|
|
|
{
|
|
|
|
int skillLevel = UserManager.getPlayer(player).getSkillLevel(abstractSubSkill.getPrimarySkill());
|
2019-01-13 08:54:53 +01:00
|
|
|
PrimarySkillType skill = abstractSubSkill.getPrimarySkill();
|
2019-01-09 04:52:52 +01:00
|
|
|
|
|
|
|
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());
|
2019-01-13 08:54:53 +01:00
|
|
|
PrimarySkillType skill = abstractSubSkill.getPrimarySkill();
|
2019-01-09 04:52:52 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-27 12:04:55 +01:00
|
|
|
/**
|
|
|
|
* Grabs static activation rolls for Secondary Abilities
|
2019-01-09 04:52:52 +01:00
|
|
|
* @param subSkillType The secondary ability to grab properties of
|
2018-12-27 12:04:55 +01:00
|
|
|
* @return The static activation roll involved in the RNG calculation
|
|
|
|
*/
|
2019-01-09 04:52:52 +01:00
|
|
|
public static double getSecondaryAbilityStaticChance(SubSkillType subSkillType)
|
2018-12-27 12:04:55 +01:00
|
|
|
{
|
2019-01-09 04:52:52 +01:00
|
|
|
switch(subSkillType)
|
2018-12-27 12:04:55 +01:00
|
|
|
{
|
2018-12-29 14:24:55 +01:00
|
|
|
case AXES_ARMOR_IMPACT:
|
2018-12-27 12:04:55 +01:00
|
|
|
return AdvancedConfig.getInstance().getImpactChance();
|
2018-12-29 14:24:55 +01:00
|
|
|
case AXES_GREATER_IMPACT:
|
2018-12-27 12:04:55 +01:00
|
|
|
return AdvancedConfig.getInstance().getGreaterImpactChance();
|
2019-01-04 16:58:39 +01:00
|
|
|
case TAMING_FAST_FOOD_SERVICE:
|
2018-12-27 12:04:55 +01:00
|
|
|
return AdvancedConfig.getInstance().getFastFoodChance();
|
|
|
|
default:
|
|
|
|
return 100.0D;
|
|
|
|
}
|
2018-12-27 08:59:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-12-27 12:04:55 +01:00
|
|
|
* Used to determine whether or not a sub-skill activates from random chance (using static values)
|
2019-01-09 04:52:52 +01:00
|
|
|
* @param subSkillType The identifier for this specific sub-skill
|
2018-12-27 12:04:55 +01:00
|
|
|
* @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
|
2018-12-27 08:59:43 +01:00
|
|
|
*/
|
2019-01-09 04:52:52 +01:00
|
|
|
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);
|
2013-11-22 18:32:23 +01:00
|
|
|
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
2014-05-11 14:58:08 +02:00
|
|
|
return (event.getChance() * activationChance) > Misc.getRandom().nextInt(activationChance) && !event.isCancelled();
|
|
|
|
}
|
|
|
|
|
2014-01-20 22:58:40 +01:00
|
|
|
public static boolean treasureDropSuccessful(Player player, double dropChance, int activationChance) {
|
2019-01-09 04:52:52 +01:00
|
|
|
SubSkillWeightedActivationCheckEvent event = new SubSkillWeightedActivationCheckEvent(player, SubSkillType.EXCAVATION_TREASURE_HUNTER, dropChance / activationChance);
|
2013-11-22 18:32:23 +01:00
|
|
|
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
2014-05-11 14:58:08 +02:00
|
|
|
return (event.getChance() * activationChance) > (Misc.getRandom().nextDouble() * activationChance) && !event.isCancelled();
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|
2013-10-15 19:03:33 +02:00
|
|
|
|
|
|
|
private static boolean isLocalizedSkill(String skillName) {
|
2019-01-13 08:54:53 +01:00
|
|
|
for (PrimarySkillType skill : PrimarySkillType.values()) {
|
2013-10-15 19:03:33 +02:00
|
|
|
if (skillName.equalsIgnoreCase(LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".SkillName"))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2013-03-06 18:31:48 +01:00
|
|
|
|
|
|
|
protected static Material getRepairAndSalvageItem(ItemStack inHand) {
|
|
|
|
if (ItemUtils.isDiamondTool(inHand) || ItemUtils.isDiamondArmor(inHand)) {
|
|
|
|
return Material.DIAMOND;
|
|
|
|
}
|
|
|
|
else if (ItemUtils.isGoldTool(inHand) || ItemUtils.isGoldArmor(inHand)) {
|
|
|
|
return Material.GOLD_INGOT;
|
|
|
|
}
|
|
|
|
else if (ItemUtils.isIronTool(inHand) || ItemUtils.isIronArmor(inHand)) {
|
|
|
|
return Material.IRON_INGOT;
|
|
|
|
}
|
|
|
|
else if (ItemUtils.isStoneTool(inHand)) {
|
|
|
|
return Material.COBBLESTONE;
|
|
|
|
}
|
|
|
|
else if (ItemUtils.isWoodTool(inHand)) {
|
2018-07-27 01:53:29 +02:00
|
|
|
return Material.OAK_WOOD;
|
2013-03-06 18:31:48 +01:00
|
|
|
}
|
|
|
|
else if (ItemUtils.isLeatherArmor(inHand)) {
|
|
|
|
return Material.LEATHER;
|
|
|
|
}
|
|
|
|
else if (ItemUtils.isStringTool(inHand)) {
|
|
|
|
return Material.STRING;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int getRepairAndSalvageQuantities(ItemStack item) {
|
|
|
|
return getRepairAndSalvageQuantities(item, getRepairAndSalvageItem(item), (byte) -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int getRepairAndSalvageQuantities(ItemStack item, Material repairMaterial, byte repairMetadata) {
|
2013-12-14 14:27:50 +01:00
|
|
|
// Workaround for Bukkit bug where damaged items would not return any recipes
|
|
|
|
item = item.clone();
|
|
|
|
item.setDurability((short) 0);
|
|
|
|
|
2013-03-06 18:31:48 +01:00
|
|
|
int quantity = 0;
|
|
|
|
List<Recipe> recipes = mcMMO.p.getServer().getRecipesFor(item);
|
|
|
|
|
2013-12-14 14:27:50 +01:00
|
|
|
if (recipes.isEmpty()) {
|
|
|
|
return quantity;
|
|
|
|
}
|
2013-03-06 18:31:48 +01:00
|
|
|
|
2013-12-14 14:27:50 +01:00
|
|
|
Recipe recipe = recipes.get(0);
|
|
|
|
|
|
|
|
if (recipe instanceof ShapelessRecipe) {
|
|
|
|
for (ItemStack ingredient : ((ShapelessRecipe) recipe).getIngredientList()) {
|
2018-08-04 00:21:13 +02:00
|
|
|
if (ingredient != null && (repairMaterial == null || ingredient.getType() == repairMaterial) && (repairMetadata == -1 || ingredient.getType().equals(repairMaterial))) {
|
2013-12-14 14:27:50 +01:00
|
|
|
quantity += ingredient.getAmount();
|
2013-03-06 18:31:48 +01:00
|
|
|
}
|
|
|
|
}
|
2013-12-14 14:27:50 +01:00
|
|
|
}
|
|
|
|
else if (recipe instanceof ShapedRecipe) {
|
|
|
|
for (ItemStack ingredient : ((ShapedRecipe) recipe).getIngredientMap().values()) {
|
2018-08-04 00:21:13 +02:00
|
|
|
if (ingredient != null && (repairMaterial == null || ingredient.getType() == repairMaterial) && (repairMetadata == -1 || ingredient.getType().equals(repairMaterial))) {
|
2013-12-14 14:27:50 +01:00
|
|
|
quantity += ingredient.getAmount();
|
2013-03-06 18:31:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return quantity;
|
|
|
|
}
|
2013-03-01 06:52:01 +01:00
|
|
|
}
|