SalvageManager.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. package com.gmail.nossr50.skills.salvage;
  2. import com.gmail.nossr50.datatypes.interactions.NotificationType;
  3. import com.gmail.nossr50.datatypes.player.McMMOPlayer;
  4. import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
  5. import com.gmail.nossr50.datatypes.skills.SubSkillType;
  6. import com.gmail.nossr50.datatypes.skills.behaviours.SalvageBehaviour;
  7. import com.gmail.nossr50.mcMMO;
  8. import com.gmail.nossr50.skills.SkillManager;
  9. import com.gmail.nossr50.skills.salvage.salvageables.Salvageable;
  10. import com.gmail.nossr50.util.Misc;
  11. import com.gmail.nossr50.util.Permissions;
  12. import com.gmail.nossr50.util.StringUtils;
  13. import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
  14. import com.gmail.nossr50.util.sounds.SoundManager;
  15. import com.gmail.nossr50.util.sounds.SoundType;
  16. import org.bukkit.Location;
  17. import org.bukkit.Material;
  18. import org.bukkit.enchantments.Enchantment;
  19. import org.bukkit.entity.Player;
  20. import org.bukkit.inventory.ItemStack;
  21. import org.bukkit.inventory.meta.EnchantmentStorageMeta;
  22. import java.util.Map;
  23. import java.util.Map.Entry;
  24. public class SalvageManager extends SkillManager {
  25. private boolean placedAnvil;
  26. private int lastClick;
  27. private SalvageBehaviour salvageBehaviour;
  28. public SalvageManager(mcMMO pluginRef, McMMOPlayer mcMMOPlayer) {
  29. super(pluginRef, mcMMOPlayer, PrimarySkillType.SALVAGE);
  30. this.salvageBehaviour = pluginRef.getDynamicSettingsManager().getSkillBehaviourManager().getSalvageBehaviour();
  31. }
  32. /**
  33. * Handles notifications for placing an anvil.
  34. */
  35. public void placedAnvilCheck() {
  36. Player player = getPlayer();
  37. if (getPlacedAnvil()) {
  38. return;
  39. }
  40. if (pluginRef.getConfigManager().getConfigSalvage().getGeneral().isAnvilMessages()) {
  41. pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Salvage.Listener.Anvil");
  42. }
  43. if (pluginRef.getConfigManager().getConfigSalvage().getGeneral().isAnvilPlacedSounds()) {
  44. SoundManager.sendSound(player, player.getLocation(), SoundType.ANVIL);
  45. }
  46. togglePlacedAnvil();
  47. }
  48. public void handleSalvage(Location location, ItemStack item) {
  49. Player player = getPlayer();
  50. Salvageable salvageable = pluginRef.getSalvageableManager().getSalvageable(item.getType());
  51. if (item.getItemMeta().isUnbreakable()) {
  52. pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Anvil.Unbreakable");
  53. return;
  54. }
  55. // Permissions checks on material and item types
  56. if (!Permissions.salvageItemType(player, salvageable.getSalvageItemType())) {
  57. pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.NO_PERMISSION, "mcMMO.NoPermission");
  58. return;
  59. }
  60. if (!Permissions.salvageMaterialType(player, salvageable.getSalvageItemMaterialCategory())) {
  61. pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.NO_PERMISSION, "mcMMO.NoPermission");
  62. return;
  63. }
  64. /*int skillLevel = getSkillLevel();
  65. int minimumSalvageableLevel = salvageable.getMinimumLevel();*/
  66. // Level check
  67. if (!pluginRef.getRankTools().hasUnlockedSubskill(player, SubSkillType.SALVAGE_ARCANE_SALVAGE)) {
  68. pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.REQUIREMENTS_NOT_MET, "Salvage.Skills.Adept.Level", String.valueOf(pluginRef.getRankTools().getUnlockLevel(SubSkillType.SALVAGE_ARCANE_SALVAGE)), StringUtils.getPrettyItemString(item.getType()));
  69. return;
  70. }
  71. int potentialSalvageYield = salvageBehaviour.calculateSalvageableAmount(item.getDurability(), salvageable.getMaximumDurability(), salvageable.getMaximumQuantity());
  72. if (potentialSalvageYield <= 0) {
  73. pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Salvage.Skills.TooDamaged");
  74. return;
  75. }
  76. potentialSalvageYield = Math.min(potentialSalvageYield, getSalvageLimit()); // Always get at least something back, if you're capable of salvaging it.
  77. player.getInventory().setItemInMainHand(new ItemStack(Material.AIR));
  78. location.add(0.5, 1, 0.5);
  79. Map<Enchantment, Integer> enchants = item.getEnchantments();
  80. ItemStack enchantBook = null;
  81. if (!enchants.isEmpty()) {
  82. enchantBook = arcaneSalvageCheck(enchants);
  83. }
  84. //Lottery on Salvageable Amount
  85. int lotteryResults = 1;
  86. int chanceOfSuccess = 99;
  87. for(int x = 0; x < potentialSalvageYield-1; x++) {
  88. if(pluginRef.getRandomChanceTools().rollDice(chanceOfSuccess, 100)) {
  89. chanceOfSuccess-=2;
  90. Math.max(chanceOfSuccess, 95);
  91. lotteryResults+=1;
  92. }
  93. }
  94. if(lotteryResults == potentialSalvageYield && potentialSalvageYield != 1 && pluginRef.getRankTools().isPlayerMaxRankInSubSkill(player, SubSkillType.SALVAGE_ARCANE_SALVAGE)) {
  95. pluginRef.getNotificationManager().sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Perfect", String.valueOf(lotteryResults), StringUtils.getPrettyItemString(item.getType()));
  96. } else if(salvageable.getMaximumQuantity() == 1 || getSalvageLimit() >= salvageable.getMaximumQuantity()) {
  97. pluginRef.getNotificationManager().sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Normal", String.valueOf(lotteryResults), StringUtils.getPrettyItemString(item.getType()));
  98. } else {
  99. pluginRef.getNotificationManager().sendPlayerInformationChatOnly(player, "Salvage.Skills.Lottery.Untrained", String.valueOf(lotteryResults), StringUtils.getPrettyItemString(item.getType()));
  100. }
  101. ItemStack salvageResults = new ItemStack(salvageable.getSalvagedItemMaterial(), lotteryResults);
  102. //Call event
  103. if (pluginRef.getEventManager().callSalvageCheckEvent(player, item, salvageResults, enchantBook).isCancelled()) {
  104. return;
  105. }
  106. Location anvilLoc = location.clone();
  107. Location playerLoc = player.getLocation().clone();
  108. double distance = anvilLoc.distance(playerLoc);
  109. double speedLimit = .6;
  110. double minSpeed = .3;
  111. //Clamp the speed and vary it by distance
  112. double vectorSpeed = Math.min(speedLimit, Math.max(minSpeed, distance * .2));
  113. //Add a very small amount of height
  114. anvilLoc.add(0, .1, 0);
  115. if (enchantBook != null) {
  116. Misc.spawnItemTowardsLocation(anvilLoc.clone(), playerLoc.clone(), enchantBook, vectorSpeed);
  117. }
  118. Misc.spawnItemTowardsLocation(anvilLoc.clone(), playerLoc.clone(), salvageResults, vectorSpeed);
  119. // BWONG BWONG BWONG - CLUNK!
  120. if (pluginRef.getConfigManager().getConfigSalvage().getGeneral().isAnvilUseSounds()) {
  121. SoundManager.sendSound(player, player.getLocation(), SoundType.ITEM_BREAK);
  122. }
  123. pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Salvage.Skills.Success");
  124. }
  125. /*public double getMaxSalvagePercentage() {
  126. return Math.min((((Salvage.salvageMaxPercentage / Salvage.salvageMaxPercentageLevel) * getSkillLevel()) / 100.0D), Salvage.salvageMaxPercentage / 100.0D);
  127. }*/
  128. public int getSalvageLimit() {
  129. return (pluginRef.getRankTools().getRank(getPlayer(), SubSkillType.SALVAGE_SCRAP_COLLECTOR));
  130. }
  131. /**
  132. * Gets the Arcane Salvage rank
  133. *
  134. * @return the current Arcane Salvage rank
  135. */
  136. public int getArcaneSalvageRank() {
  137. return pluginRef.getRankTools().getRank(getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE);
  138. }
  139. /*public double getExtractFullEnchantChance() {
  140. int skillLevel = getSkillLevel();
  141. for (Tier tier : Tier.values()) {
  142. if (skillLevel >= tier.getLevel()) {
  143. return tier.getExtractFullEnchantChance();
  144. }
  145. }
  146. return 0;
  147. }
  148. public double getExtractPartialEnchantChance() {
  149. int skillLevel = getSkillLevel();
  150. for (Tier tier : Tier.values()) {
  151. if (skillLevel >= tier.getLevel()) {
  152. return tier.getExtractPartialEnchantChance();
  153. }
  154. }
  155. return 0;
  156. }*/
  157. public double getExtractFullEnchantChance() {
  158. if (Permissions.hasSalvageEnchantBypassPerk(getPlayer()))
  159. return 100.0D;
  160. return pluginRef.getConfigManager().getConfigSalvage().getConfigArcaneSalvage().getExtractFullEnchantChance().get(getArcaneSalvageRank());
  161. }
  162. public double getExtractPartialEnchantChance() {
  163. return pluginRef.getConfigManager().getConfigSalvage().getConfigArcaneSalvage().getExtractPartialEnchantChance().get(getArcaneSalvageRank());
  164. }
  165. private ItemStack arcaneSalvageCheck(Map<Enchantment, Integer> enchants) {
  166. Player player = getPlayer();
  167. if (!pluginRef.getRankTools().hasUnlockedSubskill(player, SubSkillType.SALVAGE_ARCANE_SALVAGE) || !Permissions.arcaneSalvage(player)) {
  168. pluginRef.getNotificationManager().sendPlayerInformationChatOnly(player, "Salvage.Skills.ArcaneFailed");
  169. return null;
  170. }
  171. ItemStack book = new ItemStack(Material.ENCHANTED_BOOK);
  172. EnchantmentStorageMeta enchantMeta = (EnchantmentStorageMeta) book.getItemMeta();
  173. boolean downgraded = false;
  174. int arcaneFailureCount = 0;
  175. for (Entry<Enchantment, Integer> enchant : enchants.entrySet()) {
  176. int enchantLevel = enchant.getValue();
  177. if(!pluginRef.getConfigManager().getConfigExploitPrevention().getConfigSectionExploitSkills().getConfigSectionExploitSalvage().isAllowUnsafeEnchants()) {
  178. if(enchantLevel > enchant.getKey().getMaxLevel()) {
  179. enchantLevel = enchant.getKey().getMaxLevel();
  180. }
  181. }
  182. if (!salvageBehaviour.isArcaneSalvageEnchantLoss()
  183. || Permissions.hasSalvageEnchantBypassPerk(player)
  184. || pluginRef.getRandomChanceTools().checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getExtractFullEnchantChance(), getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE))) {
  185. enchantMeta.addStoredEnchant(enchant.getKey(), enchantLevel, true);
  186. }
  187. else if (enchantLevel > 1
  188. && salvageBehaviour.isArcaneSalvageDowngrades()
  189. && pluginRef.getRandomChanceTools().checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getExtractPartialEnchantChance(), getPlayer(), SubSkillType.SALVAGE_ARCANE_SALVAGE))) {
  190. enchantMeta.addStoredEnchant(enchant.getKey(), enchantLevel - 1, true);
  191. downgraded = true;
  192. } else {
  193. arcaneFailureCount++;
  194. }
  195. }
  196. if(failedAllEnchants(arcaneFailureCount, enchants.entrySet().size()))
  197. {
  198. pluginRef.getNotificationManager().sendPlayerInformationChatOnly(player, "Salvage.Skills.ArcaneFailed");
  199. return null;
  200. } else if(downgraded)
  201. {
  202. pluginRef.getNotificationManager().sendPlayerInformationChatOnly(player, "Salvage.Skills.ArcanePartial");
  203. }
  204. book.setItemMeta(enchantMeta);
  205. return book;
  206. }
  207. private boolean failedAllEnchants(int arcaneFailureCount, int size) {
  208. return arcaneFailureCount == size;
  209. }
  210. /**
  211. * Check if the player has tried to use an Anvil before.
  212. *
  213. * @param actualize
  214. * @return true if the player has confirmed using an Anvil
  215. */
  216. public boolean checkConfirmation(boolean actualize) {
  217. Player player = getPlayer();
  218. long lastUse = getLastAnvilUse();
  219. if (!pluginRef.getSkillTools().cooldownExpired(lastUse, 3) || !pluginRef.getConfigManager().getConfigSalvage().getGeneral().isEnchantedItemsRequireConfirm()) {
  220. return true;
  221. }
  222. if (!actualize) {
  223. return false;
  224. }
  225. actualizeLastAnvilUse();
  226. pluginRef.getNotificationManager().sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Skills.ConfirmOrCancel", pluginRef.getLocaleManager().getString("Salvage.Pretty.Name"));
  227. return false;
  228. }
  229. /*
  230. * Salvage Anvil Placement
  231. */
  232. public boolean getPlacedAnvil() {
  233. return placedAnvil;
  234. }
  235. public void togglePlacedAnvil() {
  236. placedAnvil = !placedAnvil;
  237. }
  238. /*
  239. * Salvage Anvil Usage
  240. */
  241. public int getLastAnvilUse() {
  242. return lastClick;
  243. }
  244. public void setLastAnvilUse(int value) {
  245. lastClick = value;
  246. }
  247. public void actualizeLastAnvilUse() {
  248. lastClick = (int) (System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR);
  249. }
  250. }