SalvageManager.java 11 KB

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