mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-10-18 18:13:39 +02:00
e7e62b8d40
Fire SecondaryAbilityEvent for abilities with static chances Also cleanup some of the event handling for Armor Impact, Greater Impact and Fast Food
305 lines
13 KiB
Java
305 lines
13 KiB
Java
package com.gmail.nossr50.util.skills;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.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.material.MaterialData;
|
|
import org.bukkit.potion.PotionEffect;
|
|
import org.bukkit.potion.PotionEffectType;
|
|
|
|
import com.gmail.nossr50.mcMMO;
|
|
import com.gmail.nossr50.config.AdvancedConfig;
|
|
import com.gmail.nossr50.config.Config;
|
|
import com.gmail.nossr50.config.HiddenConfig;
|
|
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
|
import com.gmail.nossr50.datatypes.skills.AbilityType;
|
|
import com.gmail.nossr50.datatypes.skills.SecondaryAbility;
|
|
import com.gmail.nossr50.datatypes.skills.SkillType;
|
|
import com.gmail.nossr50.events.skills.secondaryabilities.SecondaryAbilityEvent;
|
|
import com.gmail.nossr50.events.skills.secondaryabilities.SecondaryAbilityWeightedActivationCheckEvent;
|
|
import com.gmail.nossr50.locale.LocaleLoader;
|
|
import com.gmail.nossr50.util.EventUtils;
|
|
import com.gmail.nossr50.util.ItemUtils;
|
|
import com.gmail.nossr50.util.Misc;
|
|
import com.gmail.nossr50.util.StringUtils;
|
|
import com.gmail.nossr50.util.player.UserManager;
|
|
|
|
public class SkillUtils {
|
|
public static int handleFoodSkills(Player player, SkillType skill, int eventFoodLevel, int baseLevel, int maxLevel, int rankChange) {
|
|
int skillLevel = UserManager.getPlayer(player).getSkillLevel(skill);
|
|
|
|
int currentFoodLevel = player.getFoodLevel();
|
|
int foodChange = eventFoodLevel - currentFoodLevel;
|
|
|
|
for (int i = baseLevel; i <= maxLevel; i += rankChange) {
|
|
if (skillLevel >= i) {
|
|
foodChange++;
|
|
}
|
|
}
|
|
|
|
return currentFoodLevel + foodChange;
|
|
}
|
|
|
|
/**
|
|
* Calculate the time remaining until the cooldown expires.
|
|
*
|
|
* @param deactivatedTimeStamp Time of deactivation
|
|
* @param cooldown The length of the cooldown
|
|
* @param player The Player to check for cooldown perks
|
|
*
|
|
* @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);
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
return System.currentTimeMillis() >= (deactivatedTimeStamp + cooldown) * Misc.TIME_CONVERSION_FACTOR;
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
return Config.getInstance().getLocale().equalsIgnoreCase("en_US") ? SkillType.getSkill(skillName) != null : isLocalizedSkill(skillName);
|
|
}
|
|
|
|
public static void sendSkillMessage(Player player, String message) {
|
|
Location location = player.getLocation();
|
|
|
|
for (Player otherPlayer : player.getWorld().getPlayers()) {
|
|
if (otherPlayer != player && Misc.isNear(location, otherPlayer.getLocation(), Misc.SKILL_MESSAGE_MAX_SENDING_DISTANCE)) {
|
|
otherPlayer.sendMessage(message);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void handleAbilitySpeedIncrease(Player player) {
|
|
if (HiddenConfig.getInstance().useEnchantmentBuffs()) {
|
|
ItemStack heldItem = player.getItemInHand();
|
|
|
|
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");
|
|
itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel + AdvancedConfig.getInstance().getEnchantBuff(), true);
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
|
|
SkillType skill = mcMMOPlayer.getAbilityMode(AbilityType.SUPER_BREAKER) ? SkillType.MINING : SkillType.EXCAVATION;
|
|
int ticks = PerksUtils.handleActivationPerks(player, 2 + (mcMMOPlayer.getSkillLevel(skill) / AdvancedConfig.getInstance().getAbilityLength()), skill.getAbility().getMaxLength()) * Misc.TICK_CONVERSION_FACTOR;
|
|
|
|
PotionEffect abilityBuff = new PotionEffect(PotionEffectType.FAST_DIGGING, duration + ticks, amplifier + 10);
|
|
player.addPotionEffect(abilityBuff, true);
|
|
}
|
|
}
|
|
|
|
public static void handleAbilitySpeedDecrease(Player player) {
|
|
if (!HiddenConfig.getInstance().useEnchantmentBuffs()) {
|
|
return;
|
|
}
|
|
|
|
for (ItemStack item : player.getInventory().getContents()) {
|
|
removeAbilityBuff(item);
|
|
}
|
|
}
|
|
|
|
public static void removeAbilityBuff(ItemStack item) {
|
|
if (item == null || item.getType() == Material.AIR || (!ItemUtils.isPickaxe(item) && !ItemUtils.isShovel(item)) || !item.containsEnchantment(Enchantment.DIG_SPEED)) {
|
|
return;
|
|
}
|
|
|
|
ItemMeta itemMeta = item.getItemMeta();
|
|
|
|
if (itemMeta.hasLore()) {
|
|
List<String> itemLore = itemMeta.getLore();
|
|
|
|
if (itemLore.remove("mcMMO Ability Tool")) {
|
|
int efficiencyLevel = item.getEnchantmentLevel(Enchantment.DIG_SPEED);
|
|
|
|
if (efficiencyLevel <= AdvancedConfig.getInstance().getEnchantBuff()) {
|
|
itemMeta.removeEnchant(Enchantment.DIG_SPEED);
|
|
}
|
|
else {
|
|
itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel - AdvancedConfig.getInstance().getEnchantBuff(), true);
|
|
}
|
|
|
|
itemMeta.setLore(itemLore);
|
|
item.setItemMeta(itemMeta);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void handleDurabilityChange(ItemStack itemStack, int durabilityModifier) {
|
|
handleDurabilityChange(itemStack, durabilityModifier, 1.0);
|
|
}
|
|
|
|
/**
|
|
* Modify the durability of an ItemStack.
|
|
*
|
|
* @param itemStack The ItemStack which durability should be modified
|
|
* @param durabilityModifier the amount to modify the durability by
|
|
* @param maxDamageModifier the amount to adjust the max damage by
|
|
*/
|
|
public static void handleDurabilityChange(ItemStack itemStack, int durabilityModifier, double maxDamageModifier) {
|
|
Material type = itemStack.getType();
|
|
short maxDurability = mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability();
|
|
durabilityModifier = (int) Math.min(durabilityModifier / (itemStack.getEnchantmentLevel(Enchantment.DURABILITY) + 1), maxDurability * maxDamageModifier);
|
|
|
|
itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
|
|
}
|
|
|
|
public static boolean activationSuccessful(SecondaryAbility skillAbility, Player player, SkillType skill) {
|
|
return activationSuccessful(skillAbility, player, UserManager.getPlayer(player).getSkillLevel(skill), PerksUtils.handleLuckyPerks(player, skill));
|
|
}
|
|
|
|
public static boolean activationSuccessful(SecondaryAbility skillAbility, Player player, int skillLevel, int activationChance) {
|
|
return activationSuccessful(skillAbility, player, skillLevel, activationChance, AdvancedConfig.getInstance().getMaxChance(skillAbility), AdvancedConfig.getInstance().getMaxBonusLevel(skillAbility));
|
|
}
|
|
|
|
public static boolean activationSuccessful(SecondaryAbility skillAbility, Player player, int skillLevel, int activationChance, double maxChance, int maxLevel) {
|
|
double chance = (maxChance / maxLevel) * Math.min(skillLevel, maxLevel) / activationChance;
|
|
SecondaryAbilityWeightedActivationCheckEvent event = new SecondaryAbilityWeightedActivationCheckEvent(player, skillAbility, chance);
|
|
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
|
return (event.getChance() * activationChance) > Misc.getRandom().nextInt(activationChance) && !event.isCancelled();
|
|
}
|
|
|
|
public static boolean activationSuccessful(SecondaryAbility skillAbility, Player player, double staticChance, int activationChance) {
|
|
double chance = staticChance / activationChance;
|
|
SecondaryAbilityWeightedActivationCheckEvent event = new SecondaryAbilityWeightedActivationCheckEvent(player, skillAbility, chance);
|
|
mcMMO.p.getServer().getPluginManager().callEvent(event);
|
|
return (event.getChance() * activationChance) > Misc.getRandom().nextInt(activationChance) && !event.isCancelled();
|
|
}
|
|
|
|
public static boolean activationSuccessful(SecondaryAbility skillAbility, Player player) {
|
|
SecondaryAbilityEvent event = EventUtils.callSecondaryAbilityEvent(player, skillAbility);
|
|
return !event.isCancelled();
|
|
}
|
|
|
|
public static boolean treasureDropSuccessful(Player player, double dropChance, int activationChance) {
|
|
SecondaryAbilityWeightedActivationCheckEvent event = new SecondaryAbilityWeightedActivationCheckEvent(player, SecondaryAbility.EXCAVATION_TREASURE_HUNTER, 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 (SkillType skill : SkillType.values()) {
|
|
if (skillName.equalsIgnoreCase(LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".SkillName"))) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
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)) {
|
|
return Material.WOOD;
|
|
}
|
|
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) {
|
|
// Workaround for Bukkit bug where damaged items would not return any recipes
|
|
item = item.clone();
|
|
item.setDurability((short) 0);
|
|
|
|
int quantity = 0;
|
|
MaterialData repairData = repairMaterial != null ? new MaterialData(repairMaterial, repairMetadata) : null;
|
|
List<Recipe> recipes = mcMMO.p.getServer().getRecipesFor(item);
|
|
|
|
if (recipes.isEmpty()) {
|
|
return quantity;
|
|
}
|
|
|
|
Recipe recipe = recipes.get(0);
|
|
|
|
if (recipe instanceof ShapelessRecipe) {
|
|
for (ItemStack ingredient : ((ShapelessRecipe) recipe).getIngredientList()) {
|
|
if (ingredient != null && (repairMaterial == null || ingredient.getType() == repairMaterial) && (repairMetadata == -1 || ingredient.getData().equals(repairData))) {
|
|
quantity += ingredient.getAmount();
|
|
}
|
|
}
|
|
}
|
|
else if (recipe instanceof ShapedRecipe) {
|
|
for (ItemStack ingredient : ((ShapedRecipe) recipe).getIngredientMap().values()) {
|
|
if (ingredient != null && (repairMaterial == null || ingredient.getType() == repairMaterial) && (repairMetadata == -1 || ingredient.getData().equals(repairData))) {
|
|
quantity += ingredient.getAmount();
|
|
}
|
|
}
|
|
}
|
|
|
|
return quantity;
|
|
}
|
|
}
|