SkillUtils.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. package com.gmail.nossr50.util.skills;
  2. import com.gmail.nossr50.config.AdvancedConfig;
  3. import com.gmail.nossr50.config.Config;
  4. import com.gmail.nossr50.config.HiddenConfig;
  5. import com.gmail.nossr50.datatypes.experience.XPGainReason;
  6. import com.gmail.nossr50.datatypes.experience.XPGainSource;
  7. import com.gmail.nossr50.datatypes.interactions.NotificationType;
  8. import com.gmail.nossr50.datatypes.player.McMMOPlayer;
  9. import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
  10. import com.gmail.nossr50.datatypes.skills.SubSkillType;
  11. import com.gmail.nossr50.datatypes.skills.SuperAbilityType;
  12. import com.gmail.nossr50.locale.LocaleLoader;
  13. import com.gmail.nossr50.mcMMO;
  14. import com.gmail.nossr50.util.ItemUtils;
  15. import com.gmail.nossr50.util.Misc;
  16. import com.gmail.nossr50.util.StringUtils;
  17. import com.gmail.nossr50.util.compat.layers.persistentdata.AbstractPersistentDataLayer;
  18. import com.gmail.nossr50.util.player.NotificationManager;
  19. import com.gmail.nossr50.util.player.UserManager;
  20. import org.bukkit.Bukkit;
  21. import org.bukkit.Location;
  22. import org.bukkit.Material;
  23. import org.bukkit.enchantments.Enchantment;
  24. import org.bukkit.entity.Player;
  25. import org.bukkit.inventory.ItemStack;
  26. import org.bukkit.inventory.Recipe;
  27. import org.bukkit.inventory.ShapedRecipe;
  28. import org.bukkit.inventory.ShapelessRecipe;
  29. import org.bukkit.potion.PotionEffect;
  30. import org.bukkit.potion.PotionEffectType;
  31. import org.jetbrains.annotations.NotNull;
  32. import org.jetbrains.annotations.Nullable;
  33. import java.util.Iterator;
  34. public class SkillUtils {
  35. public static void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason) {
  36. mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, XPGainSource.SELF);
  37. }
  38. public static void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason, XPGainSource xpGainSource) {
  39. mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, xpGainSource);
  40. }
  41. /*
  42. * Skill Stat Calculations
  43. */
  44. public static String[] calculateLengthDisplayValues(Player player, float skillValue, PrimarySkillType skill) {
  45. int maxLength = skill.getAbility().getMaxLength();
  46. int abilityLengthVar = AdvancedConfig.getInstance().getAbilityLength();
  47. int abilityLengthCap = AdvancedConfig.getInstance().getAbilityLengthCap();
  48. int length;
  49. if(abilityLengthCap > 0)
  50. {
  51. length = (int) Math.min(abilityLengthCap, 2 + (skillValue / abilityLengthVar));
  52. } else {
  53. length = 2 + (int) (skillValue / abilityLengthVar);
  54. }
  55. int enduranceLength = PerksUtils.handleActivationPerks(player, length, maxLength);
  56. if (maxLength != 0) {
  57. length = Math.min(length, maxLength);
  58. }
  59. return new String[] { String.valueOf(length), String.valueOf(enduranceLength) };
  60. }
  61. /*
  62. * Others
  63. */
  64. public static int handleFoodSkills(Player player, int eventFoodLevel, SubSkillType subSkillType) {
  65. int curRank = RankUtils.getRank(player, subSkillType);
  66. int currentFoodLevel = player.getFoodLevel();
  67. int foodChange = eventFoodLevel - currentFoodLevel;
  68. foodChange+=curRank;
  69. return currentFoodLevel + foodChange;
  70. }
  71. /**
  72. * Calculate the time remaining until the cooldown expires.
  73. *
  74. * @param deactivatedTimeStamp Time of deactivation
  75. * @param cooldown The length of the cooldown
  76. * @param player The Player to check for cooldown perks
  77. *
  78. * @return the number of seconds remaining before the cooldown expires
  79. */
  80. public static int calculateTimeLeft(long deactivatedTimeStamp, int cooldown, Player player) {
  81. return (int) (((deactivatedTimeStamp + (PerksUtils.handleCooldownPerks(player, cooldown) * Misc.TIME_CONVERSION_FACTOR)) - System.currentTimeMillis()) / Misc.TIME_CONVERSION_FACTOR);
  82. }
  83. /**
  84. * Check if the cooldown has expired.
  85. * This does NOT account for cooldown perks!
  86. *
  87. * @param deactivatedTimeStamp Time of deactivation in seconds
  88. * @param cooldown The length of the cooldown in seconds
  89. *
  90. * @return true if the cooldown is expired
  91. */
  92. public static boolean cooldownExpired(long deactivatedTimeStamp, int cooldown) {
  93. return System.currentTimeMillis() >= (deactivatedTimeStamp + cooldown) * Misc.TIME_CONVERSION_FACTOR;
  94. }
  95. /**
  96. * Checks if the given string represents a valid skill
  97. *
  98. * @param skillName The name of the skill to check
  99. * @return true if this is a valid skill, false otherwise
  100. */
  101. public static boolean isSkill(String skillName) {
  102. return Config.getInstance().getLocale().equalsIgnoreCase("en_US") ? PrimarySkillType.getSkill(skillName) != null : isLocalizedSkill(skillName);
  103. }
  104. public static void sendSkillMessage(Player player, NotificationType notificationType, String key) {
  105. Location location = player.getLocation();
  106. for (Player otherPlayer : player.getWorld().getPlayers()) {
  107. if (otherPlayer != player && Misc.isNear(location, otherPlayer.getLocation(), Misc.SKILL_MESSAGE_MAX_SENDING_DISTANCE)) {
  108. NotificationManager.sendNearbyPlayersInformation(otherPlayer, notificationType, key, player.getName());
  109. }
  110. }
  111. }
  112. public static void handleAbilitySpeedIncrease(Player player) {
  113. if (HiddenConfig.getInstance().useEnchantmentBuffs()) {
  114. ItemStack heldItem = player.getInventory().getItemInMainHand();
  115. if(heldItem == null)
  116. return;
  117. if (!ItemUtils.canBeSuperAbilityDigBoosted(heldItem)) {
  118. return;
  119. }
  120. int originalDigSpeed = heldItem.getEnchantmentLevel(Enchantment.DIG_SPEED);
  121. //Add lore, add dig speed
  122. ItemUtils.addAbilityLore(heldItem); //lore can be a secondary failsafe for 1.13 and below
  123. ItemUtils.addDigSpeedToItem(heldItem, heldItem.getEnchantmentLevel(Enchantment.DIG_SPEED));
  124. //1.14+ will have persistent metadata for this item
  125. AbstractPersistentDataLayer compatLayer = mcMMO.getCompatibilityManager().getPersistentDataLayer();
  126. compatLayer.setSuperAbilityBoostedItem(heldItem, originalDigSpeed);
  127. }
  128. else {
  129. int duration = 0;
  130. int amplifier = 0;
  131. if (player.hasPotionEffect(PotionEffectType.FAST_DIGGING)) {
  132. for (PotionEffect effect : player.getActivePotionEffects()) {
  133. if (effect.getType() == PotionEffectType.FAST_DIGGING) {
  134. duration = effect.getDuration();
  135. amplifier = effect.getAmplifier();
  136. break;
  137. }
  138. }
  139. }
  140. McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
  141. //Not Loaded
  142. if(mcMMOPlayer == null)
  143. return;
  144. PrimarySkillType skill = mcMMOPlayer.getAbilityMode(SuperAbilityType.SUPER_BREAKER) ? PrimarySkillType.MINING : PrimarySkillType.EXCAVATION;
  145. int abilityLengthVar = AdvancedConfig.getInstance().getAbilityLength();
  146. int abilityLengthCap = AdvancedConfig.getInstance().getAbilityLengthCap();
  147. int ticks;
  148. if(abilityLengthCap > 0)
  149. {
  150. ticks = PerksUtils.handleActivationPerks(player, Math.min(abilityLengthCap, 2 + (mcMMOPlayer.getSkillLevel(skill) / abilityLengthVar)),
  151. skill.getAbility().getMaxLength()) * Misc.TICK_CONVERSION_FACTOR;
  152. } else {
  153. ticks = PerksUtils.handleActivationPerks(player, 2 + ((mcMMOPlayer.getSkillLevel(skill)) / abilityLengthVar),
  154. skill.getAbility().getMaxLength()) * Misc.TICK_CONVERSION_FACTOR;
  155. }
  156. PotionEffect abilityBuff = new PotionEffect(PotionEffectType.FAST_DIGGING, duration + ticks, amplifier + 10);
  157. player.addPotionEffect(abilityBuff, true);
  158. }
  159. }
  160. public static void removeAbilityBoostsFromInventory(@NotNull Player player) {
  161. if (!HiddenConfig.getInstance().useEnchantmentBuffs()) {
  162. return;
  163. }
  164. for (ItemStack itemStack : player.getInventory().getContents()) {
  165. removeAbilityBuff(itemStack);
  166. }
  167. }
  168. public static void removeAbilityBuff(@Nullable ItemStack itemStack) {
  169. if(itemStack == null)
  170. return;
  171. if(!ItemUtils.canBeSuperAbilityDigBoosted(itemStack))
  172. return;
  173. //Take the lore off
  174. ItemUtils.removeAbilityLore(itemStack);
  175. //1.14+ will have persistent metadata for this itemStack
  176. AbstractPersistentDataLayer compatLayer = mcMMO.getCompatibilityManager().getPersistentDataLayer();
  177. if(compatLayer.isSuperAbilityBoosted(itemStack))
  178. compatLayer.removeBonusDigSpeedOnSuperAbilityTool(itemStack);
  179. }
  180. public static void handleDurabilityChange(ItemStack itemStack, int durabilityModifier) {
  181. handleDurabilityChange(itemStack, durabilityModifier, 1.0);
  182. }
  183. /**
  184. * Modify the durability of an ItemStack.
  185. *
  186. * @param itemStack The ItemStack which durability should be modified
  187. * @param durabilityModifier the amount to modify the durability by
  188. * @param maxDamageModifier the amount to adjust the max damage by
  189. */
  190. public static void handleDurabilityChange(ItemStack itemStack, double durabilityModifier, double maxDamageModifier) {
  191. if(itemStack.getItemMeta() != null && itemStack.getItemMeta().isUnbreakable()) {
  192. return;
  193. }
  194. Material type = itemStack.getType();
  195. short maxDurability = mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability();
  196. durabilityModifier = (int) Math.min(durabilityModifier / (itemStack.getEnchantmentLevel(Enchantment.DURABILITY) + 1), maxDurability * maxDamageModifier);
  197. itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
  198. }
  199. private static boolean isLocalizedSkill(String skillName) {
  200. for (PrimarySkillType skill : PrimarySkillType.values()) {
  201. if (skillName.equalsIgnoreCase(LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".SkillName"))) {
  202. return true;
  203. }
  204. }
  205. return false;
  206. }
  207. protected static Material getRepairAndSalvageItem(ItemStack inHand) {
  208. if (ItemUtils.isDiamondTool(inHand) || ItemUtils.isDiamondArmor(inHand)) {
  209. return Material.DIAMOND;
  210. }
  211. else if (ItemUtils.isGoldTool(inHand) || ItemUtils.isGoldArmor(inHand)) {
  212. return Material.GOLD_INGOT;
  213. }
  214. else if (ItemUtils.isIronTool(inHand) || ItemUtils.isIronArmor(inHand)) {
  215. return Material.IRON_INGOT;
  216. }
  217. else if (ItemUtils.isStoneTool(inHand)) {
  218. return Material.COBBLESTONE;
  219. }
  220. else if (ItemUtils.isWoodTool(inHand)) {
  221. return Material.OAK_WOOD;
  222. }
  223. else if (ItemUtils.isLeatherArmor(inHand)) {
  224. return Material.LEATHER;
  225. }
  226. else if (ItemUtils.isStringTool(inHand)) {
  227. return Material.STRING;
  228. }
  229. else {
  230. return null;
  231. }
  232. }
  233. public static int getRepairAndSalvageQuantities(ItemStack item) {
  234. return getRepairAndSalvageQuantities(item.getType(), getRepairAndSalvageItem(item));
  235. }
  236. public static int getRepairAndSalvageQuantities(Material itemMaterial, Material recipeMaterial) {
  237. int quantity = 0;
  238. if(mcMMO.getMaterialMapStore().isNetheriteTool(itemMaterial) || mcMMO.getMaterialMapStore().isNetheriteArmor(itemMaterial)) {
  239. //One netherite bar requires 4 netherite scraps
  240. return 4;
  241. }
  242. for(Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator(); recipeIterator.hasNext();) {
  243. Recipe bukkitRecipe = recipeIterator.next();
  244. if(bukkitRecipe.getResult().getType() != itemMaterial)
  245. continue;
  246. if(bukkitRecipe instanceof ShapelessRecipe) {
  247. for (ItemStack ingredient : ((ShapelessRecipe) bukkitRecipe).getIngredientList()) {
  248. if (ingredient != null
  249. && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
  250. && (ingredient.getType() == recipeMaterial)) {
  251. quantity += ingredient.getAmount();
  252. }
  253. }
  254. } else if(bukkitRecipe instanceof ShapedRecipe) {
  255. for (ItemStack ingredient : ((ShapedRecipe) bukkitRecipe).getIngredientMap().values()) {
  256. if (ingredient != null
  257. && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
  258. && (ingredient.getType() == recipeMaterial)) {
  259. quantity += ingredient.getAmount();
  260. }
  261. }
  262. }
  263. }
  264. return quantity;
  265. }
  266. }