RepairManager.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. package com.gmail.nossr50.skills.repair;
  2. import com.gmail.nossr50.config.AdvancedConfig;
  3. import com.gmail.nossr50.config.experience.ExperienceConfig;
  4. import com.gmail.nossr50.datatypes.experience.XPGainReason;
  5. import com.gmail.nossr50.datatypes.interactions.NotificationType;
  6. import com.gmail.nossr50.datatypes.player.McMMOPlayer;
  7. import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
  8. import com.gmail.nossr50.datatypes.skills.SubSkillType;
  9. import com.gmail.nossr50.locale.LocaleLoader;
  10. import com.gmail.nossr50.mcMMO;
  11. import com.gmail.nossr50.skills.SkillManager;
  12. import com.gmail.nossr50.skills.repair.repairables.Repairable;
  13. import com.gmail.nossr50.util.EventUtils;
  14. import com.gmail.nossr50.util.Misc;
  15. import com.gmail.nossr50.util.Permissions;
  16. import com.gmail.nossr50.util.StringUtils;
  17. import com.gmail.nossr50.util.player.NotificationManager;
  18. import com.gmail.nossr50.util.random.RandomChanceSkillStatic;
  19. import com.gmail.nossr50.util.random.RandomChanceUtil;
  20. import com.gmail.nossr50.util.skills.RankUtils;
  21. import com.gmail.nossr50.util.skills.SkillActivationType;
  22. import com.gmail.nossr50.util.skills.SkillUtils;
  23. import com.gmail.nossr50.util.sounds.SoundManager;
  24. import com.gmail.nossr50.util.sounds.SoundType;
  25. import org.bukkit.Material;
  26. import org.bukkit.enchantments.Enchantment;
  27. import org.bukkit.entity.Player;
  28. import org.bukkit.inventory.ItemStack;
  29. import org.bukkit.inventory.PlayerInventory;
  30. import java.util.Map;
  31. import java.util.Map.Entry;
  32. public class RepairManager extends SkillManager {
  33. private boolean placedAnvil;
  34. private int lastClick;
  35. public RepairManager(McMMOPlayer mcMMOPlayer) {
  36. super(mcMMOPlayer, PrimarySkillType.REPAIR);
  37. }
  38. /**
  39. * Handles notifications for placing an anvil.
  40. */
  41. public void placedAnvilCheck() {
  42. Player player = getPlayer();
  43. if (getPlacedAnvil()) {
  44. return;
  45. }
  46. if (mcMMO.getConfigManager().getConfigRepair().getRepairGeneral().isAnvilMessages()) {
  47. NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Repair.Listener.Anvil");
  48. }
  49. if (mcMMO.getConfigManager().getConfigRepair().getRepairGeneral().isAnvilPlacedSounds()) {
  50. SoundManager.sendSound(player, player.getLocation(), SoundType.ANVIL);
  51. }
  52. togglePlacedAnvil();
  53. }
  54. public void handleRepair(ItemStack item) {
  55. Player player = getPlayer();
  56. Repairable repairable = mcMMO.getRepairableManager().getRepairable(item.getType());
  57. if (item.getItemMeta().isUnbreakable()) {
  58. NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Anvil.Unbreakable");
  59. return;
  60. }
  61. // Permissions checks on material and item types
  62. if (!Permissions.repairMaterialType(player, repairable.getRepairItemMaterialCategory())) {
  63. NotificationManager.sendPlayerInformation(player, NotificationType.NO_PERMISSION, "mcMMO.NoPermission");
  64. return;
  65. }
  66. if (!Permissions.repairItemType(player, repairable.getRepairItemType())) {
  67. NotificationManager.sendPlayerInformation(player, NotificationType.NO_PERMISSION, "mcMMO.NoPermission");
  68. return;
  69. }
  70. int skillLevel = getSkillLevel();
  71. int minimumRepairableLevel = repairable.getMinimumLevel();
  72. // Level check
  73. if (skillLevel < minimumRepairableLevel) {
  74. NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Skills.Adept", String.valueOf(minimumRepairableLevel), StringUtils.getPrettyItemString(item.getType()));
  75. return;
  76. }
  77. PlayerInventory inventory = player.getInventory();
  78. Material repairMaterial = null;
  79. //Find the first compatible repair material
  80. for(Material repairMaterialCandidate : repairable.getRepairMaterials())
  81. {
  82. if(player.getInventory().contains(new ItemStack(repairMaterialCandidate)))
  83. repairMaterial = repairMaterialCandidate;
  84. }
  85. //byte repairMaterialMetadata = repairable.getRepairMaterialMetadata();
  86. ItemStack toRemove = new ItemStack(repairMaterial);
  87. short startDurability = item.getDurability();
  88. // Do not repair if at full durability
  89. if (startDurability <= 0) {
  90. NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Skills.FullDurability");
  91. return;
  92. }
  93. // Check if they have the proper material to repair with
  94. /*if (!inventory.contains(repairMaterial)) {
  95. String prettyName = repairable.getRepairMaterialPrettyName() == null ? StringUtils.getPrettyItemString(repairMaterial) : repairable.getRepairMaterialPrettyName();
  96. String materialsNeeded = "";
  97. if (repairMaterialMetadata != (byte) -1 && !inventory.containsAtLeast(toRemove, 1)) {
  98. materialsNeeded += ":" + repairMaterialMetadata;
  99. }
  100. NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Skills.NeedMore.Extra", prettyName, materialsNeeded);
  101. return;
  102. }*/
  103. // Do not repair stacked items
  104. if (item.getAmount() != 1) {
  105. NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Skills.StackedItems");
  106. return;
  107. }
  108. // Clear ability buffs before trying to repair.
  109. SkillUtils.removeAbilityBuff(item);
  110. // Lets get down to business,
  111. // To defeat, the huns.
  112. int baseRepairAmount = repairable.getBaseRepairDurability(); // Did they send me daughters?
  113. short newDurability = repairCalculate(startDurability, baseRepairAmount); // When I asked for sons?
  114. // Call event
  115. if (EventUtils.callRepairCheckEvent(player, (short) (startDurability - newDurability), toRemove, item).isCancelled()) {
  116. return;
  117. }
  118. // Handle the enchants
  119. // if (ArcaneForging.arcaneForgingEnchantLoss) {
  120. if (mcMMO.getConfigManager().getConfigRepair().getArcaneForging().isMayLoseEnchants()) {
  121. addEnchants(item);
  122. }
  123. // Remove the item
  124. /*if (repairMaterialMetadata == -1) {
  125. toRemove = inventory.getItem(inventory.first(repairMaterial)).clone();
  126. toRemove.setAmount(1);
  127. }*/
  128. inventory.removeItem(toRemove);
  129. // Give out XP like candy
  130. applyXpGain((float) ((getPercentageRepaired(startDurability, newDurability, repairable.getMaximumDurability()) * repairable.getXpMultiplier()) * ExperienceConfig.getInstance().getRepairXPBase() * ExperienceConfig.getInstance().getRepairXP(repairable.getRepairItemMaterialCategory())), XPGainReason.PVE);
  131. // BWONG BWONG BWONG
  132. if (mcMMO.getConfigManager().getConfigRepair().getRepairGeneral().isAnvilUseSounds()) {
  133. SoundManager.sendSound(player, player.getLocation(), SoundType.ANVIL);
  134. SoundManager.sendSound(player, player.getLocation(), SoundType.ITEM_BREAK);
  135. }
  136. // Repair the item!
  137. item.setDurability(newDurability);
  138. }
  139. private float getPercentageRepaired(short startDurability, short newDurability, short totalDurability) {
  140. return ((startDurability - newDurability) / (float) totalDurability);
  141. }
  142. /**
  143. * Check if the player has tried to use an Anvil before.
  144. *
  145. * @return true if the player has confirmed using an Anvil
  146. */
  147. public boolean checkConfirmation(boolean actualize) {
  148. Player player = getPlayer();
  149. long lastUse = getLastAnvilUse();
  150. if (!SkillUtils.cooldownExpired(lastUse, 3) || !mcMMO.getConfigManager().getConfigRepair().getRepairGeneral().isEnchantedItemsRequireConfirm()) {
  151. return true;
  152. }
  153. if (!actualize) {
  154. return false;
  155. }
  156. actualizeLastAnvilUse();
  157. NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Skills.ConfirmOrCancel", LocaleLoader.getString("Repair.Pretty.Name"));
  158. return false;
  159. }
  160. /**
  161. * Gets the Arcane Forging rank
  162. *
  163. * @return the current Arcane Forging rank
  164. */
  165. public int getArcaneForgingRank() {
  166. return RankUtils.getRank(getPlayer(), SubSkillType.REPAIR_ARCANE_FORGING);
  167. }
  168. /**
  169. * Gets chance of keeping enchantment during repair.
  170. *
  171. * @return The chance of keeping the enchantment
  172. */
  173. public double getKeepEnchantChance() {
  174. return AdvancedConfig.getInstance().getArcaneForgingKeepEnchantsChance(getArcaneForgingRank());
  175. }
  176. /**
  177. * Gets chance of enchantment being downgraded during repair.
  178. *
  179. * @return The chance of the enchantment being downgraded
  180. */
  181. public double getDowngradeEnchantChance() {
  182. return AdvancedConfig.getInstance().getArcaneForgingDowngradeChance(getArcaneForgingRank());
  183. }
  184. /**
  185. * Gets chance of keeping enchantment during repair.
  186. *
  187. * @return The chance of keeping the enchantment
  188. */
  189. /*public double getKeepEnchantChance() {
  190. int skillLevel = getSkillLevel();
  191. for (Tier tier : Tier.values()) {
  192. if (skillLevel >= tier.getLevel()) {
  193. return tier.getKeepEnchantChance();
  194. }
  195. }
  196. return 0;
  197. }*/
  198. /**
  199. * Gets chance of enchantment being downgraded during repair.
  200. *
  201. * @return The chance of the enchantment being downgraded
  202. */
  203. /*public double getDowngradeEnchantChance() {
  204. int skillLevel = getSkillLevel();
  205. for (Tier tier : Tier.values()) {
  206. if (skillLevel >= tier.getLevel()) {
  207. return tier.getDowngradeEnchantChance();
  208. }
  209. }
  210. return 100;
  211. }*/
  212. /**
  213. * Computes repair bonuses.
  214. *
  215. * @param durability The durability of the item being repaired
  216. * @param repairAmount The base amount of durability repaired to the item
  217. * @return The final amount of durability repaired to the item
  218. */
  219. private short repairCalculate(short durability, int repairAmount) {
  220. Player player = getPlayer();
  221. if (Permissions.isSubSkillEnabled(player, SubSkillType.REPAIR_REPAIR_MASTERY)
  222. && RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.REPAIR_REPAIR_MASTERY)) {
  223. double maxBonusCalc = Repair.getInstance().getRepairMasteryMaxBonus() / 100.0D;
  224. double skillLevelBonusCalc = (Repair.getInstance().getRepairMasteryMaxBonus() / Repair.getInstance().getRepairMasteryMaxBonusLevel()) * (getSkillLevel() / 100.0D);
  225. double bonus = repairAmount * Math.min(skillLevelBonusCalc, maxBonusCalc);
  226. repairAmount += bonus;
  227. }
  228. if (Permissions.isSubSkillEnabled(player, SubSkillType.REPAIR_SUPER_REPAIR) && checkPlayerProcRepair()) {
  229. repairAmount *= 2.0D;
  230. }
  231. if (repairAmount <= 0 || repairAmount > Short.MAX_VALUE) {
  232. repairAmount = Short.MAX_VALUE;
  233. }
  234. return (short) Math.max(durability - repairAmount, 0);
  235. }
  236. /**
  237. * Checks for Super Repair bonus.
  238. *
  239. * @return true if bonus granted, false otherwise
  240. */
  241. private boolean checkPlayerProcRepair() {
  242. if(!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.REPAIR_SUPER_REPAIR))
  243. return false;
  244. if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.REPAIR_SUPER_REPAIR, getPlayer())) {
  245. NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Repair.Skills.FeltEasy");
  246. return true;
  247. }
  248. return false;
  249. }
  250. /**
  251. * Handles removing & downgrading enchants.
  252. *
  253. * @param item Item being repaired
  254. */
  255. private void addEnchants(ItemStack item) {
  256. Player player = getPlayer();
  257. Map<Enchantment, Integer> enchants = item.getEnchantments();
  258. if (enchants.isEmpty()) {
  259. return;
  260. }
  261. if (Permissions.arcaneBypass(player)) {
  262. NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Repair.Arcane.Perfect");
  263. return;
  264. }
  265. if (getArcaneForgingRank() == 0 || !Permissions.isSubSkillEnabled(player, SubSkillType.REPAIR_ARCANE_FORGING)) {
  266. for (Enchantment enchant : enchants.keySet()) {
  267. item.removeEnchantment(enchant);
  268. }
  269. NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Arcane.Lost");
  270. return;
  271. }
  272. boolean downgraded = false;
  273. for (Entry<Enchantment, Integer> enchant : enchants.entrySet()) {
  274. Enchantment enchantment = enchant.getKey();
  275. if (RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(getKeepEnchantChance(), getPlayer(), SubSkillType.REPAIR_ARCANE_FORGING))) {
  276. int enchantLevel = enchant.getValue();
  277. if (mcMMO.getConfigManager().getConfigRepair().getArcaneForging().isDowngradesEnabled() && enchantLevel > 1
  278. && (!RandomChanceUtil.checkRandomChanceExecutionSuccess(new RandomChanceSkillStatic(100 - getDowngradeEnchantChance(), getPlayer(), SubSkillType.REPAIR_ARCANE_FORGING)))) {
  279. item.addUnsafeEnchantment(enchantment, enchantLevel - 1);
  280. downgraded = true;
  281. }
  282. }
  283. else {
  284. item.removeEnchantment(enchantment);
  285. }
  286. }
  287. Map<Enchantment, Integer> newEnchants = item.getEnchantments();
  288. if (newEnchants.isEmpty()) {
  289. NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Arcane.Fail");
  290. }
  291. else if (downgraded || newEnchants.size() < enchants.size()) {
  292. NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE_FAILED, "Repair.Arcane.Downgrade");
  293. }
  294. else {
  295. NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Repair.Arcane.Perfect");
  296. }
  297. }
  298. /*
  299. * Repair Anvil Placement
  300. */
  301. public boolean getPlacedAnvil() {
  302. return placedAnvil;
  303. }
  304. public void togglePlacedAnvil() {
  305. placedAnvil = !placedAnvil;
  306. }
  307. /*
  308. * Repair Anvil Usage
  309. */
  310. public int getLastAnvilUse() {
  311. return lastClick;
  312. }
  313. public void setLastAnvilUse(int value) {
  314. lastClick = value;
  315. }
  316. public void actualizeLastAnvilUse() {
  317. lastClick = (int) (System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR);
  318. }
  319. }