SkillUtils.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  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.experience.ExperienceBarManager;
  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.inventory.meta.ItemMeta;
  30. import org.bukkit.potion.PotionEffect;
  31. import org.bukkit.potion.PotionEffectType;
  32. import java.util.ArrayList;
  33. import java.util.HashMap;
  34. import java.util.Iterator;
  35. import java.util.List;
  36. public class SkillUtils {
  37. public static void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason) {
  38. mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, XPGainSource.SELF);
  39. }
  40. public static void applyXpGain(McMMOPlayer mcMMOPlayer, PrimarySkillType skill, float xp, XPGainReason xpGainReason, XPGainSource xpGainSource) {
  41. mcMMOPlayer.beginXpGain(skill, xp, xpGainReason, xpGainSource);
  42. }
  43. public static HashMap<PrimarySkillType, ExperienceBarManager.BarState> generateDefaultBarStateMap() {
  44. HashMap<PrimarySkillType, ExperienceBarManager.BarState> barStateHashMap = new HashMap<>();
  45. setBarStateDefaults(barStateHashMap);
  46. return barStateHashMap;
  47. }
  48. public static ExperienceBarManager.BarState asBarState(String str) {
  49. for(ExperienceBarManager.BarState barState : ExperienceBarManager.BarState.values()) {
  50. if(barState.toString().equalsIgnoreCase(str)) {
  51. return barState;
  52. }
  53. }
  54. return ExperienceBarManager.BarState.NORMAL;
  55. }
  56. public static void setBarStateDefaults(HashMap<PrimarySkillType, ExperienceBarManager.BarState> barStateHashMap) {
  57. for(PrimarySkillType skillType : PrimarySkillType.values()) {
  58. if(skillType.isChildSkill()) {
  59. barStateHashMap.put(skillType, ExperienceBarManager.BarState.DISABLED);
  60. } else {
  61. barStateHashMap.put(skillType, ExperienceBarManager.BarState.NORMAL);
  62. }
  63. }
  64. }
  65. /*
  66. * Skill Stat Calculations
  67. */
  68. public static String[] calculateLengthDisplayValues(Player player, float skillValue, PrimarySkillType skill) {
  69. int maxLength = skill.getSuperAbilityType().getMaxLength();
  70. int abilityLengthVar = AdvancedConfig.getInstance().getAbilityLength();
  71. int abilityLengthCap = AdvancedConfig.getInstance().getAbilityLengthCap();
  72. int length;
  73. if(abilityLengthCap > 0)
  74. {
  75. length = (int) Math.min(abilityLengthCap, 2 + (skillValue / abilityLengthVar));
  76. } else {
  77. length = 2 + (int) (skillValue / abilityLengthVar);
  78. }
  79. int enduranceLength = PerksUtils.handleActivationPerks(player, length, maxLength);
  80. if (maxLength != 0) {
  81. length = Math.min(length, maxLength);
  82. }
  83. return new String[] { String.valueOf(length), String.valueOf(enduranceLength) };
  84. }
  85. /*
  86. * Others
  87. */
  88. public static int handleFoodSkills(Player player, int eventFoodLevel, SubSkillType subSkillType) {
  89. int curRank = RankUtils.getRank(player, subSkillType);
  90. int currentFoodLevel = player.getFoodLevel();
  91. int foodChange = eventFoodLevel - currentFoodLevel;
  92. foodChange+=curRank;
  93. return currentFoodLevel + foodChange;
  94. }
  95. /**
  96. * Calculate the time remaining until the cooldown expires.
  97. *
  98. * @param deactivatedTimeStamp Time of deactivation
  99. * @param cooldown The length of the cooldown
  100. * @param player The Player to check for cooldown perks
  101. *
  102. * @return the number of seconds remaining before the cooldown expires
  103. */
  104. public static int calculateTimeLeft(long deactivatedTimeStamp, int cooldown, Player player) {
  105. return (int) (((deactivatedTimeStamp + (PerksUtils.handleCooldownPerks(player, cooldown) * Misc.TIME_CONVERSION_FACTOR)) - System.currentTimeMillis()) / Misc.TIME_CONVERSION_FACTOR);
  106. }
  107. /**
  108. * Check if the cooldown has expired.
  109. * This does NOT account for cooldown perks!
  110. *
  111. * @param deactivatedTimeStamp Time of deactivation in seconds
  112. * @param cooldown The length of the cooldown in seconds
  113. *
  114. * @return true if the cooldown is expired
  115. */
  116. public static boolean cooldownExpired(long deactivatedTimeStamp, int cooldown) {
  117. return System.currentTimeMillis() >= (deactivatedTimeStamp + cooldown) * Misc.TIME_CONVERSION_FACTOR;
  118. }
  119. /**
  120. * Checks if the given string represents a valid skill
  121. *
  122. * @param skillName The name of the skill to check
  123. * @return true if this is a valid skill, false otherwise
  124. */
  125. public static boolean isSkill(String skillName) {
  126. return Config.getInstance().getLocale().equalsIgnoreCase("en_US") ? PrimarySkillType.getSkill(skillName) != null : isLocalizedSkill(skillName);
  127. }
  128. public static void sendSkillMessage(Player player, NotificationType notificationType, String key) {
  129. Location location = player.getLocation();
  130. for (Player otherPlayer : player.getWorld().getPlayers()) {
  131. if (otherPlayer != player && Misc.isNear(location, otherPlayer.getLocation(), Misc.SKILL_MESSAGE_MAX_SENDING_DISTANCE)) {
  132. NotificationManager.sendNearbyPlayersInformation(otherPlayer, notificationType, key, player.getName());
  133. }
  134. }
  135. }
  136. public static void handleAbilitySpeedIncrease(Player player) {
  137. if (HiddenConfig.getInstance().useEnchantmentBuffs()) {
  138. ItemStack heldItem = player.getInventory().getItemInMainHand();
  139. if (heldItem == null || heldItem.getType() == Material.AIR) {
  140. return;
  141. }
  142. int efficiencyLevel = heldItem.getEnchantmentLevel(Enchantment.DIG_SPEED);
  143. ItemMeta itemMeta = heldItem.getItemMeta();
  144. List<String> itemLore = new ArrayList<>();
  145. if (itemMeta.hasLore()) {
  146. itemLore = itemMeta.getLore();
  147. }
  148. itemLore.add("mcMMO Ability Tool");
  149. itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel + AdvancedConfig.getInstance().getEnchantBuff(), true);
  150. itemMeta.setLore(itemLore);
  151. heldItem.setItemMeta(itemMeta);
  152. }
  153. else {
  154. int duration = 0;
  155. int amplifier = 0;
  156. if (player.hasPotionEffect(PotionEffectType.FAST_DIGGING)) {
  157. for (PotionEffect effect : player.getActivePotionEffects()) {
  158. if (effect.getType() == PotionEffectType.FAST_DIGGING) {
  159. duration = effect.getDuration();
  160. amplifier = effect.getAmplifier();
  161. break;
  162. }
  163. }
  164. }
  165. McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
  166. //Not Loaded
  167. if(mcMMOPlayer == null)
  168. return;
  169. PrimarySkillType skill = mcMMOPlayer.getSuperAbilityManager().getAbilityMode(SuperAbilityType.SUPER_BREAKER) ? PrimarySkillType.MINING : PrimarySkillType.EXCAVATION;
  170. int abilityLengthVar = AdvancedConfig.getInstance().getAbilityLength();
  171. int abilityLengthCap = AdvancedConfig.getInstance().getAbilityLengthCap();
  172. int ticks;
  173. if(abilityLengthCap > 0)
  174. {
  175. ticks = PerksUtils.handleActivationPerks(player, Math.min(abilityLengthCap, 2 + (mcMMOPlayer.getSkillLevel(skill) / abilityLengthVar)),
  176. skill.getSuperAbilityType().getMaxLength()) * Misc.TICK_CONVERSION_FACTOR;
  177. } else {
  178. ticks = PerksUtils.handleActivationPerks(player, 2 + ((mcMMOPlayer.getSkillLevel(skill)) / abilityLengthVar),
  179. skill.getSuperAbilityType().getMaxLength()) * Misc.TICK_CONVERSION_FACTOR;
  180. }
  181. PotionEffect abilityBuff = new PotionEffect(PotionEffectType.FAST_DIGGING, duration + ticks, amplifier + 10);
  182. player.addPotionEffect(abilityBuff, true);
  183. }
  184. }
  185. public static void handleAbilitySpeedDecrease(Player player) {
  186. if (!HiddenConfig.getInstance().useEnchantmentBuffs()) {
  187. return;
  188. }
  189. for (ItemStack item : player.getInventory().getContents()) {
  190. removeAbilityBuff(item);
  191. }
  192. }
  193. public static void removeAbilityBuff(ItemStack item) {
  194. if (item == null || item.getType() == Material.AIR || (!ItemUtils.isPickaxe(item) && !ItemUtils.isShovel(item)) || !item.containsEnchantment(Enchantment.DIG_SPEED)) {
  195. return;
  196. }
  197. ItemMeta itemMeta = item.getItemMeta();
  198. if (itemMeta.hasLore()) {
  199. List<String> itemLore = itemMeta.getLore();
  200. if (itemLore.remove("mcMMO Ability Tool")) {
  201. int efficiencyLevel = item.getEnchantmentLevel(Enchantment.DIG_SPEED);
  202. if (efficiencyLevel <= AdvancedConfig.getInstance().getEnchantBuff()) {
  203. itemMeta.removeEnchant(Enchantment.DIG_SPEED);
  204. }
  205. else {
  206. itemMeta.addEnchant(Enchantment.DIG_SPEED, efficiencyLevel - AdvancedConfig.getInstance().getEnchantBuff(), true);
  207. }
  208. itemMeta.setLore(itemLore);
  209. item.setItemMeta(itemMeta);
  210. }
  211. }
  212. }
  213. public static void handleDurabilityChange(ItemStack itemStack, int durabilityModifier) {
  214. handleDurabilityChange(itemStack, durabilityModifier, 1.0);
  215. }
  216. /**
  217. * Modify the durability of an ItemStack.
  218. *
  219. * @param itemStack The ItemStack which durability should be modified
  220. * @param durabilityModifier the amount to modify the durability by
  221. * @param maxDamageModifier the amount to adjust the max damage by
  222. */
  223. public static void handleDurabilityChange(ItemStack itemStack, double durabilityModifier, double maxDamageModifier) {
  224. if(itemStack.getItemMeta() != null && itemStack.getItemMeta().isUnbreakable()) {
  225. return;
  226. }
  227. Material type = itemStack.getType();
  228. short maxDurability = mcMMO.getRepairableManager().isRepairable(type) ? mcMMO.getRepairableManager().getRepairable(type).getMaximumDurability() : type.getMaxDurability();
  229. durabilityModifier = (int) Math.min(durabilityModifier / (itemStack.getEnchantmentLevel(Enchantment.DURABILITY) + 1), maxDurability * maxDamageModifier);
  230. itemStack.setDurability((short) Math.min(itemStack.getDurability() + durabilityModifier, maxDurability));
  231. }
  232. private static boolean isLocalizedSkill(String skillName) {
  233. for (PrimarySkillType skill : PrimarySkillType.values()) {
  234. if (skillName.equalsIgnoreCase(LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".SkillName"))) {
  235. return true;
  236. }
  237. }
  238. return false;
  239. }
  240. protected static Material getRepairAndSalvageItem(ItemStack inHand) {
  241. if (ItemUtils.isDiamondTool(inHand) || ItemUtils.isDiamondArmor(inHand)) {
  242. return Material.DIAMOND;
  243. }
  244. else if (ItemUtils.isGoldTool(inHand) || ItemUtils.isGoldArmor(inHand)) {
  245. return Material.GOLD_INGOT;
  246. }
  247. else if (ItemUtils.isIronTool(inHand) || ItemUtils.isIronArmor(inHand)) {
  248. return Material.IRON_INGOT;
  249. }
  250. else if (ItemUtils.isStoneTool(inHand)) {
  251. return Material.COBBLESTONE;
  252. }
  253. else if (ItemUtils.isWoodTool(inHand)) {
  254. return Material.OAK_WOOD;
  255. }
  256. else if (ItemUtils.isLeatherArmor(inHand)) {
  257. return Material.LEATHER;
  258. }
  259. else if (ItemUtils.isStringTool(inHand)) {
  260. return Material.STRING;
  261. }
  262. else {
  263. return null;
  264. }
  265. }
  266. public static int getRepairAndSalvageQuantities(ItemStack item) {
  267. return getRepairAndSalvageQuantities(item.getType(), getRepairAndSalvageItem(item));
  268. }
  269. public static int getRepairAndSalvageQuantities(Material itemMaterial, Material recipeMaterial) {
  270. int quantity = 0;
  271. if(mcMMO.getMaterialMapStore().isNetheriteTool(itemMaterial) || mcMMO.getMaterialMapStore().isNetheriteArmor(itemMaterial)) {
  272. //One netherite bar requires 4 netherite scraps
  273. return 4;
  274. }
  275. for(Iterator<? extends Recipe> recipeIterator = Bukkit.getServer().recipeIterator(); recipeIterator.hasNext();) {
  276. Recipe bukkitRecipe = recipeIterator.next();
  277. if(bukkitRecipe.getResult().getType() != itemMaterial)
  278. continue;
  279. if(bukkitRecipe instanceof ShapelessRecipe) {
  280. for (ItemStack ingredient : ((ShapelessRecipe) bukkitRecipe).getIngredientList()) {
  281. if (ingredient != null
  282. && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
  283. && (ingredient.getType() == recipeMaterial)) {
  284. quantity += ingredient.getAmount();
  285. }
  286. }
  287. } else if(bukkitRecipe instanceof ShapedRecipe) {
  288. for (ItemStack ingredient : ((ShapedRecipe) bukkitRecipe).getIngredientMap().values()) {
  289. if (ingredient != null
  290. && (recipeMaterial == null || ingredient.getType() == recipeMaterial)
  291. && (ingredient.getType() == recipeMaterial)) {
  292. quantity += ingredient.getAmount();
  293. }
  294. }
  295. }
  296. }
  297. return quantity;
  298. }
  299. }