From f4d8b8bd06bd086340d2cdd4b74a5f42cb814758 Mon Sep 17 00:00:00 2001 From: UltraFaceguy Date: Tue, 25 Aug 2020 23:03:07 -0400 Subject: [PATCH] 1.16 modernization of item essences (per tier, RGB) --- pom.xml | 32 +- .../loot/items/prefabs/ShardOfFailure.java | 44 +-- .../loot/listeners/DeconstructListener.java | 67 +++- .../loot/listeners/InteractListener.java | 84 ++++- .../listeners/crafting/CraftingListener.java | 321 ++++++++++-------- .../loot/managers/LootCraftMatManager.java | 21 +- .../faceland/loot/managers/StatManager.java | 79 ++--- .../loot/menu/upgrade/EnchantMenu.java | 89 +++-- .../loot/recipe/EquipmentRecipeBuilder.java | 41 ++- .../info/faceland/loot/utils/DropUtil.java | 59 +--- .../faceland/loot/utils/InventoryUtil.java | 5 - .../faceland/loot/utils/MaterialUtil.java | 225 ++++++------ 12 files changed, 599 insertions(+), 468 deletions(-) diff --git a/pom.xml b/pom.xml index 2924dac1..d528a83b 100644 --- a/pom.xml +++ b/pom.xml @@ -30,11 +30,11 @@ io.pixeloutlaw spigot-plugin-parent - 1.16.1.0 + 1.16.2.0 loot - 1.3.9 + 1.3.10 jar loot @@ -67,23 +67,37 @@ io.pixeloutlaw facecore - 1.16.1.8 + 1.16.2.10 provided - - net.kyori - adventure-text-minimessage - 3.0.0-SNAPSHOT - io.pixeloutlaw strife - 3.1.3 + 3.2.3 com.github.MilkBowl VaultAPI 1.7 + provided + + + guava + com.google.guava + + + snakeyaml + org.yaml + + + junit + junit + + + bukkit + org.bukkit + + com.github.UltraFaceguy diff --git a/src/main/java/info/faceland/loot/items/prefabs/ShardOfFailure.java b/src/main/java/info/faceland/loot/items/prefabs/ShardOfFailure.java index 07fd3203..e82ced76 100644 --- a/src/main/java/info/faceland/loot/items/prefabs/ShardOfFailure.java +++ b/src/main/java/info/faceland/loot/items/prefabs/ShardOfFailure.java @@ -1,24 +1,23 @@ /** * The MIT License Copyright (c) 2015 Teal Cube Games *

- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - * associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: *

- * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package info.faceland.loot.items.prefabs; -import com.tealcube.minecraft.bukkit.TextUtils; +import info.faceland.loot.utils.MaterialUtil; +import io.pixeloutlaw.minecraft.spigot.garbage.ListExtensionsKt; import io.pixeloutlaw.minecraft.spigot.hilt.ItemStackExtensionsKt; import java.util.ArrayList; import java.util.Arrays; @@ -48,19 +47,20 @@ public static void rebuild() { String name = ChatColor.RED + "Shard of Failure"; FAILURE_NAME = name; ItemStackExtensionsKt.setDisplayName(stack, name); - ItemStackExtensionsKt.setLore(stack, TextUtils.color(Arrays.asList( - "&7Use this item on an Upgrade Scroll", - "&7to slightly increase the chance of", - "&7upgrade success!", - "&8&oThis failure is special because it", - "&8&owas created by {name} :)" + ItemStackExtensionsKt.setLore(stack, ListExtensionsKt.chatColorize(Arrays.asList( + "&7Place this item onto an", + "&2Upgrade Scroll &7to raise", + "&7its success chance!", + "&8&oThis failure is special", + "&8&obecause it was made by", + "&8&o{name} :)" ))); - stack.setDurability((short) 11); + ItemStackExtensionsKt.setCustomModelData(stack, 500); item = stack; } public static boolean isSimilar(ItemStack stack) { - return stack.getType() == item.getType() && stack.getDurability() == 11 && ItemStackExtensionsKt - .getDisplayName(item).equals(ItemStackExtensionsKt.getDisplayName(stack)); + return stack.getType() == item.getType() && MaterialUtil.getCustomData(stack) == 500 && FAILURE_NAME + .equals(ItemStackExtensionsKt.getDisplayName(stack)); } } diff --git a/src/main/java/info/faceland/loot/listeners/DeconstructListener.java b/src/main/java/info/faceland/loot/listeners/DeconstructListener.java index 386ecbb4..7bfe031a 100644 --- a/src/main/java/info/faceland/loot/listeners/DeconstructListener.java +++ b/src/main/java/info/faceland/loot/listeners/DeconstructListener.java @@ -13,17 +13,21 @@ import info.faceland.loot.events.LootDeconstructEvent.DeconstructType; import info.faceland.loot.items.prefabs.ShardOfFailure; import info.faceland.loot.math.LootRandom; -import info.faceland.loot.utils.InventoryUtil; +import info.faceland.loot.tier.Tier; import info.faceland.loot.utils.MaterialUtil; import io.pixeloutlaw.minecraft.spigot.hilt.ItemStackExtensionsKt; +import java.awt.Color; import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import land.face.strife.data.champion.LifeSkillType; import land.face.strife.util.PlayerDataUtil; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.Sound; +import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -135,8 +139,7 @@ private void doCraftDeconstruct(LootDeconstructEvent event) { int toolQuality = 1; if (cursorItem.hasItemMeta()) { - toolQuality = (int) ItemStackExtensionsKt.getLore(cursorItem).get(1).chars() - .filter(ch -> ch == '✪').count(); + toolQuality = (int) ItemStackExtensionsKt.getLore(cursorItem).get(1).chars().filter(ch -> ch == '✪').count(); } double levelAdvantage = getLevelAdvantage(craftingLevel, itemLevel); @@ -153,10 +156,17 @@ private void doCraftDeconstruct(LootDeconstructEvent event) { List lore = ItemStackExtensionsKt.getLore(targetItem); List possibleStats = new ArrayList<>(); for (String str : lore) { - if (str.startsWith("" + ChatColor.GREEN) || str.startsWith("" + ChatColor.YELLOW)) { - if (str.contains(":")) { - continue; + if (!ChatColor.stripColor(str).startsWith("+")) { + continue; + } + net.md_5.bungee.api.ChatColor color = getHexFromString(str); + if (color != null) { + if (isValidStealColor(color.getColor())) { + possibleStats.add(str); } + continue; + } + if (str.startsWith(ChatColor.GREEN + "") || str.startsWith(ChatColor.YELLOW + "")) { possibleStats.add(str); } } @@ -178,20 +188,28 @@ private void doCraftDeconstruct(LootDeconstructEvent event) { player.playSound(player.getEyeLocation(), Sound.ENTITY_ITEM_BREAK, 1F, 0.8F); event.setTargetItem(null); - player.getInventory().addItem(craftMaterial); + if (player.getInventory().firstEmpty() != -1) { + player.getInventory().addItem(craftMaterial); + } else { + Item item = player.getWorld().dropItem(player.getLocation(), craftMaterial); + item.setOwner(player.getUniqueId()); + } - double essChance = 0.1 + 0.1 * toolQuality + Math.min(effectiveLevelAdvantage * 0.015, 0.35); - if (possibleStats.size() > 0 && random.nextDouble() < essChance) { + if (possibleStats.size() > 0) { player.playSound(player.getEyeLocation(), Sound.ENTITY_PLAYER_LEVELUP, 0.4F, 2F); - String type = InventoryUtil.getItemType(targetItem); - ItemStack essence = buildEssence(type, itemLevel, craftingLevel, toolQuality, - possibleStats, player.hasPotionEffect(PotionEffectType.LUCK)); + Tier tier = MaterialUtil.getTierFromStack(targetItem); + + ItemStack essence = buildEssence(tier, itemLevel, effectiveLevelAdvantage, toolQuality, possibleStats, + player.hasPotionEffect(PotionEffectType.LUCK)); + if (player.getInventory().firstEmpty() != -1) { player.getInventory().addItem(essence); } else { - player.getWorld().dropItem(player.getLocation(), essence); + Item item = player.getWorld().dropItem(player.getLocation(), essence); + item.setOwner(player.getUniqueId()); } } + List toolLore = ItemStackExtensionsKt.getLore(cursorItem); if (ChatColor.stripColor(toolLore.get(toolLore.size() - 1)).startsWith("Remaining Uses: ")) { int uses = getDigit(ChatColor.stripColor(toolLore.get(toolLore.size() - 1))); @@ -205,9 +223,9 @@ private void doCraftDeconstruct(LootDeconstructEvent event) { event.setCursorItem(cursorItem); } } - double exp = 2 + Math.pow((double) itemLevel / 4, 1.2); - plugin.getStrifePlugin().getSkillExperienceManager().addExperience(player, - LifeSkillType.CRAFTING, exp, false, false); + double exp = 5 + itemLevel * 1.1; + plugin.getStrifePlugin().getSkillExperienceManager() + .addExperience(player, LifeSkillType.CRAFTING, exp, false, false); } private void doEnchantDeconstruct(LootDeconstructEvent event) { @@ -237,4 +255,21 @@ public static int getLevelAdvantage(int craftLevel, int itemLevel) { int lvlReq = 20 + (int) Math.floor((double) craftLevel / 10) * 14; return lvlReq - itemLevel; } + + private boolean isValidStealColor(Color color) { + float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); + return hsb[0] >= 0.14 && hsb[0] <= 0.34 && hsb[1] >= 0.7 && hsb[1] <= 0.72 && hsb[2] >= 0.99 && hsb[2] <= 1.01; + } + + private final Pattern hexPattern = Pattern.compile("§x(§[A-Fa-f0-9]){6}"); + + public net.md_5.bungee.api.ChatColor getHexFromString(String message) { + Matcher matcher = hexPattern.matcher(message); + if (matcher.find()) { + String str = "#" + matcher.group().replace("§x", "").replace("§", ""); + Bukkit.getLogger().warning(str); + return net.md_5.bungee.api.ChatColor.of(str); + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/info/faceland/loot/listeners/InteractListener.java b/src/main/java/info/faceland/loot/listeners/InteractListener.java index b014dbe2..828f4b0a 100644 --- a/src/main/java/info/faceland/loot/listeners/InteractListener.java +++ b/src/main/java/info/faceland/loot/listeners/InteractListener.java @@ -1,20 +1,18 @@ /** * The MIT License Copyright (c) 2015 Teal Cube Games - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - * associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package info.faceland.loot.listeners; @@ -41,6 +39,7 @@ import info.faceland.loot.tier.Tier; import info.faceland.loot.utils.InventoryUtil; import info.faceland.loot.utils.MaterialUtil; +import io.pixeloutlaw.minecraft.spigot.garbage.StringExtensionsKt; import io.pixeloutlaw.minecraft.spigot.hilt.ItemStackExtensionsKt; import java.util.ArrayList; import java.util.HashSet; @@ -163,15 +162,64 @@ public void onPlayerDropItem(PlayerDropItemEvent e) { MessageUtils.sendMessage(e.getPlayer(), noDropMessage); } + @EventHandler(priority = EventPriority.HIGHEST) + public void onQuickShard(InventoryClickEvent event) { + if (event.getClick() != ClickType.SHIFT_RIGHT || !(event.getClickedInventory() instanceof PlayerInventory)) { + return; + } + if (event.getCurrentItem() == null || event.getCursor() == null || event.getCurrentItem().getType() == Material.AIR + || event.getCursor().getType() == Material.AIR || !(event.getWhoClicked() instanceof Player)) { + return; + } + + Player player = (Player) event.getWhoClicked(); + ItemStack targetItem = new ItemStack(event.getCurrentItem()); + ItemStack cursor = new ItemStack(event.getCursor()); + String cursorName = ItemStackExtensionsKt.getDisplayName(cursor); + int amount = cursor.getAmount(); + + if (StringUtils.isBlank(cursorName) || !ShardOfFailure.isSimilar(cursor)) { + return; + } + + UpgradeScroll scroll = plugin.getScrollManager().getScroll(targetItem); + if (scroll == null) { + return; + } + if (targetItem.getAmount() > 1) { + sendMessage(player, plugin.getSettings().getString("language.augment.stack-size", "")); + return; + } + List lore = ItemStackExtensionsKt.getLore(targetItem); + int failureBonus = MaterialUtil.getFailureBonus(targetItem); + if (failureBonus > 0) { + lore.set(0, StringExtensionsKt.chatColorize(FAILURE_BONUS + " +" + (failureBonus + amount))); + } else { + lore.add(0, StringExtensionsKt.chatColorize(FAILURE_BONUS + " +" + amount)); + } + ItemStackExtensionsKt.setLore(targetItem, lore); + event.setCurrentItem(targetItem); + event.getCursor().setAmount(0); + event.setCursor(null); + event.setCancelled(true); + event.setResult(Event.Result.DENY); + player.updateInventory(); + + player.playSound(player.getEyeLocation(), Sound.BLOCK_FIRE_EXTINGUISH, 1L, 2F); + + plugin.getStrifePlugin().getSkillExperienceManager() + .addExperience(player, LifeSkillType.ENCHANTING, amount * 22, false, false); + } + @EventHandler(priority = EventPriority.HIGHEST) public void onRightClickUse(InventoryClickEvent event) { - if (!(event.getClickedInventory() instanceof PlayerInventory)) { + if (event.getClick() != ClickType.RIGHT || !(event.getClickedInventory() instanceof PlayerInventory)) { return; } if (event.getCurrentItem() == null || event.getCursor() == null || event.getCurrentItem().getType() == Material.AIR || event.getCursor().getType() == Material.AIR || - !(event.getWhoClicked() instanceof Player) || event.getClick() != ClickType.RIGHT) { + !(event.getWhoClicked() instanceof Player)) { return; } @@ -332,7 +380,7 @@ public void onRightClickUse(InventoryClickEvent event) { player.updateInventory(); player.playSound(player.getEyeLocation(), Sound.BLOCK_FIRE_EXTINGUISH, 1L, 2F); plugin.getStrifePlugin().getSkillExperienceManager().addExperience(player, - LifeSkillType.ENCHANTING, 1, false, false); + LifeSkillType.ENCHANTING, 22, false, false); } else if (cursorName.equals(ChatColor.WHITE + "Item Rename Tag")) { if (ItemStackExtensionsKt.getLore(cursor).get(3).equals(ChatColor.WHITE + "none")) { sendMessage(player, plugin.getSettings().getString("language.rename.notset", "")); diff --git a/src/main/java/info/faceland/loot/listeners/crafting/CraftingListener.java b/src/main/java/info/faceland/loot/listeners/crafting/CraftingListener.java index 94e82f11..c281932c 100644 --- a/src/main/java/info/faceland/loot/listeners/crafting/CraftingListener.java +++ b/src/main/java/info/faceland/loot/listeners/crafting/CraftingListener.java @@ -20,6 +20,7 @@ import static info.faceland.loot.utils.InventoryUtil.stripColor; import com.tealcube.minecraft.bukkit.TextUtils; +import com.tealcube.minecraft.bukkit.facecore.utilities.MessageUtils; import com.tealcube.minecraft.bukkit.shade.apache.commons.lang3.StringUtils; import com.tealcube.minecraft.bukkit.shade.apache.commons.lang3.math.NumberUtils; import com.tealcube.minecraft.bukkit.shade.google.common.base.CharMatcher; @@ -32,6 +33,8 @@ import info.faceland.loot.recipe.EquipmentRecipeBuilder; import info.faceland.loot.tier.Tier; import info.faceland.loot.utils.MaterialUtil; +import io.pixeloutlaw.minecraft.spigot.garbage.ListExtensionsKt; +import io.pixeloutlaw.minecraft.spigot.garbage.StringExtensionsKt; import io.pixeloutlaw.minecraft.spigot.hilt.ItemStackExtensionsKt; import java.util.ArrayList; import java.util.List; @@ -49,6 +52,9 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.CraftItemEvent; import org.bukkit.event.inventory.InventoryAction; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryType.SlotType; +import org.bukkit.event.inventory.PrepareItemCraftEvent; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -56,51 +62,61 @@ public final class CraftingListener implements Listener { private final LootPlugin plugin; + + public static String ESSENCE_SLOT_TEXT; + + private final String BAD_INFUSE_NAME; private final double CRAFT_EXP; private final double CRAFT_LEVEL_MULT; private final double CRAFT_QUALITY_MULT; private final double CRAFT_MASTER_MULT; - private final double BASE_INFUSE_EXP; - private final double BONUS_ESS_EXP; - private final double INFUSE_LEVEL_MULT; - private final double INFUSE_SUCCESS_MULT; - private final double INFUSE_BASE_CHANCE; private final double MAX_QUALITY; private final double MAX_SLOTS; private final double MAX_SOCKETS; - public static String ESSENCE_SLOT_TEXT; - private LootRandom random; + + private final ItemMeta dupeStatMeta; + private final ItemMeta powerfulEssenceMeta; + private final ItemMeta lowLevelMeta; + private final ItemMeta wrongTypeMeta; + private final ItemMeta noSlotsMeta; + + private final LootRandom random; public CraftingListener(LootPlugin plugin) { this.plugin = plugin; this.random = new LootRandom(); - this.CRAFT_EXP = plugin.getSettings() - .getDouble("config.crafting.base-craft-exp", 1); - this.CRAFT_LEVEL_MULT = plugin.getSettings() - .getDouble("config.crafting.craft-item-level-mult", 0.01); - this.CRAFT_QUALITY_MULT = plugin.getSettings() - .getDouble("config.crafting.craft-quality-mult", 0.1); - this.CRAFT_MASTER_MULT = plugin.getSettings() - .getDouble("config.crafting.craft-master-mult", 2.5); - this.BASE_INFUSE_EXP = plugin.getSettings() - .getDouble("config.crafting.base-infusion-exp", 4); - this.BONUS_ESS_EXP = plugin.getSettings() - .getDouble("config.crafting.infusion-exp-per-essence", 2); - this.INFUSE_LEVEL_MULT = plugin.getSettings() - .getDouble("config.crafting.infusion-item-level-mult", 0.05); - this.INFUSE_SUCCESS_MULT = plugin.getSettings() - .getDouble("config.crafting.infusion-success-mult", 2); - this.INFUSE_BASE_CHANCE = plugin.getSettings() - .getDouble("config.crafting.infusion-base-success-chance", 0.3); - this.MAX_QUALITY = plugin.getSettings() - .getDouble("config.crafting.craft-max-quality", 5); - this.MAX_SLOTS = plugin.getSettings() - .getDouble("config.crafting.craft-max-craft-slots", 5); - this.MAX_SOCKETS = plugin.getSettings() - .getDouble("config.crafting.craft-max-sockets", 3); - ESSENCE_SLOT_TEXT = TextUtils - .color(plugin.getSettings().getString("config.crafting.essence-text", "&b(Essence Slot)")); + CRAFT_EXP = plugin.getSettings().getDouble("config.crafting.base-craft-exp", 1); + CRAFT_LEVEL_MULT = plugin.getSettings().getDouble("config.crafting.craft-item-level-mult", 0.01); + CRAFT_QUALITY_MULT = plugin.getSettings().getDouble("config.crafting.craft-quality-mult", 0.1); + CRAFT_MASTER_MULT = plugin.getSettings().getDouble("config.crafting.craft-master-mult", 2.5); + MAX_QUALITY = plugin.getSettings().getDouble("config.crafting.craft-max-quality", 5); + MAX_SLOTS = plugin.getSettings().getDouble("config.crafting.craft-max-craft-slots", 5); + MAX_SOCKETS = plugin.getSettings().getDouble("config.crafting.craft-max-sockets", 3); + ESSENCE_SLOT_TEXT = StringExtensionsKt + .chatColorize(plugin.getSettings().getString("config.crafting.essence-text", "&b(Essence Slot)")); + + BAD_INFUSE_NAME = StringExtensionsKt + .chatColorize(plugin.getSettings().getString("language.essence.invalid-title", "&cCannot Use Essence!")); + + ItemStack failStack = new ItemStack(Material.BARRIER); + ItemStackExtensionsKt.setDisplayName(failStack, StringExtensionsKt.chatColorize(BAD_INFUSE_NAME)); + + dupeStatMeta = failStack.getItemMeta().clone(); + dupeStatMeta.setLore(ListExtensionsKt.chatColorize( + plugin.getSettings().getStringList("language.essence.duplicate-stats"))); + powerfulEssenceMeta = failStack.getItemMeta().clone(); + powerfulEssenceMeta.setLore(ListExtensionsKt.chatColorize( + plugin.getSettings().getStringList("language.essence.essence-strength"))); + lowLevelMeta = failStack.getItemMeta().clone(); + lowLevelMeta.setLore(ListExtensionsKt.chatColorize( + plugin.getSettings().getStringList("language.essence.low-craft-level"))); + wrongTypeMeta = failStack.getItemMeta().clone(); + wrongTypeMeta.setLore(ListExtensionsKt.chatColorize( + plugin.getSettings().getStringList("language.essence.wrong-type"))); + noSlotsMeta = failStack.getItemMeta().clone(); + noSlotsMeta.setLore(ListExtensionsKt.chatColorize( + plugin.getSettings().getStringList("language.essence.no-slots"))); } @EventHandler(priority = EventPriority.LOWEST) @@ -153,9 +169,32 @@ public void onSpecialCraftEquipment(CraftItemEvent event) { } } + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCraftEquipment(InventoryClickEvent event) { + if (event.getRawSlot() == 0 && event.getSlot() == 0 && event.getSlotType() == SlotType.RESULT) { + if (event.getClick() == ClickType.CONTROL_DROP) { + MessageUtils.sendMessage(event.getWhoClicked(), + "&e&oSorry, this crafting operation is blocked due to bugs! No items have been consumed, even if your game client may say they were until you close the crafting grid..."); + event.setCancelled(true); + return; + } + if (event.getAction() == InventoryAction.DROP_ONE_SLOT && (event.getCursor() != null + && event.getCursor().getType() != Material.AIR)) { + MessageUtils.sendMessage(event.getWhoClicked(), + "&e&oSorry, this crafting operation is blocked due to bugs! No items have been consumed, even if your game client may say they were until you close the crafting grid..."); + event.setCancelled(true); + } + } + } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onCraftEquipment(CraftItemEvent event) { + if (event.isCancelled()) { + return; + } + ItemStack resultStack = event.getCurrentItem(); + if (!plugin.getCraftBaseManager().getCraftBases().containsKey(resultStack.getType())) { return; } @@ -163,8 +202,7 @@ public void onCraftEquipment(CraftItemEvent event) { if (is == null) { continue; } - if (is.getType() == Material.PRISMARINE_SHARD || isDyeEvent(is.getType(), - resultStack.getType())) { + if (is.getType() == Material.PRISMARINE_SHARD || isDyeEvent(is.getType(), resultStack.getType())) { return; } } @@ -176,18 +214,17 @@ public void onCraftEquipment(CraftItemEvent event) { Tier tier = MaterialUtil.getTierFromStack(resultStack); if (tier == null) { - Bukkit.getLogger() - .warning("Attempted to craft item with unknown tier... " + resultStack.getType()); + Bukkit.getLogger().warning("Attempted to craft item with unknown tier... " + resultStack.getType()); return; } int craftingLevel = PlayerDataUtil.getLifeSkillLevel(player, LifeSkillType.CRAFTING); - double effectiveCraftLevel = PlayerDataUtil - .getEffectiveLifeSkill(player, LifeSkillType.CRAFTING, true); + double effectiveCraftLevel = PlayerDataUtil.getEffectiveLifeSkill(player, LifeSkillType.CRAFTING, true); int numMaterials = 0; double totalQuality = 0; double totalItemLevel = 0; + for (ItemStack is : event.getInventory().getMatrix()) { if (is == null || is.getType() == Material.AIR || is.getType() == resultStack.getType()) { continue; @@ -195,23 +232,21 @@ public void onCraftEquipment(CraftItemEvent event) { ItemStack loopItem = new ItemStack(is); if (hasItemLevel(loopItem)) { int iLevel = NumberUtils.toInt(CharMatcher.digit().or(CharMatcher.is('-')).negate() - .collapseFrom(ChatColor.stripColor(ItemStackExtensionsKt.getLore(loopItem).get(0)), ' ') - .trim()); + .collapseFrom(ChatColor.stripColor(ItemStackExtensionsKt.getLore(loopItem).get(0)), ' ').trim()); totalItemLevel += iLevel; - numMaterials++; } else { totalItemLevel += 0.5; - numMaterials++; } + numMaterials++; if (hasQuality(loopItem)) { - long count = ItemStackExtensionsKt.getLore(loopItem).get(1).chars().filter(ch -> ch == '✪') - .count(); + long count = ItemStackExtensionsKt.getLore(loopItem).get(1).chars().filter(ch -> ch == '✪').count(); totalQuality += count; } } double rawItemLevel = totalItemLevel / numMaterials; double levelAdvantage = DeconstructListener.getLevelAdvantage(craftingLevel, (int) rawItemLevel); + if (levelAdvantage < 0) { sendMessage(player, plugin.getSettings().getString("language.craft.low-level-craft", "")); player.playSound(player.getEyeLocation(), Sound.BLOCK_LAVA_POP, 0.7F, 0.5F); @@ -220,8 +255,7 @@ public void onCraftEquipment(CraftItemEvent event) { double effiLevelAdvantage = DeconstructListener.getLevelAdvantage((int) effectiveCraftLevel, (int) rawItemLevel); double skillMultiplier = 1 + Math.min(1, effiLevelAdvantage / 25); - double quality = Math - .max(1, Math.min(totalQuality / numMaterials, MAX_QUALITY) - (0.5 * random.nextDouble())); + double quality = Math.max(1, Math.min(totalQuality / numMaterials, MAX_QUALITY) - (0.5 * random.nextDouble())); double slotLuckBonus = (MAX_SLOTS - quality) * Math.pow(random.nextDouble(), 6); double craftedSlotScore = Math.max(1, quality + slotLuckBonus); @@ -229,6 +263,7 @@ public void onCraftEquipment(CraftItemEvent event) { double skillSocketRoll = skillMultiplier * 0.5 * Math.pow(random.nextDouble(), 2); double luckSocketRoll = (1 - skillMultiplier) * Math.pow(random.nextDouble(), 6); double craftedSocketScore = MAX_SOCKETS * (skillSocketRoll + luckSocketRoll); + if (skillMultiplier > 1.75) { craftedSocketScore = Math.max(2, craftedSocketScore); } else if (skillMultiplier > 1.5) { @@ -292,8 +327,7 @@ public void onCraftEquipment(CraftItemEvent event) { case NETHERITE_LEGGINGS: case NETHERITE_BOOTS: ItemMeta iMeta = newResult.getItemMeta(); - iMeta.addAttributeModifier(Attribute.GENERIC_KNOCKBACK_RESISTANCE, - LootItemBuilder.MINUS_ONE_KB_RESIST); + iMeta.addAttributeModifier(Attribute.GENERIC_KNOCKBACK_RESISTANCE, LootItemBuilder.MINUS_ONE_KB_RESIST); newResult.setItemMeta(iMeta); } MaterialUtil.applyTierLevelData(newResult, tier, itemLevel); @@ -321,121 +355,119 @@ public void onCraftEquipment(CraftItemEvent event) { player.playSound(player.getEyeLocation(), Sound.BLOCK_ANVIL_FALL, 0.5F, 1F); } - @EventHandler(priority = EventPriority.MONITOR) - public void onEssenceInfuse(CraftItemEvent event) { - if (event.isCancelled()) { - return; - } - if (!(event.getCursor() == null || event.getCursor().getType() == Material.AIR)) { - return; - } - ItemStack resultStack = event.getCurrentItem(); - if (!resultStack.hasItemMeta() || !resultStack.getItemMeta().hasDisplayName()) { - return; - } - if (!resultStack.getItemMeta().getDisplayName().equals(EquipmentRecipeBuilder.INFUSE_NAME)) { + @EventHandler + public void onEssenceInfuse(PrepareItemCraftEvent event) { + + if (event.getRecipe() == null) { return; } - event.setCancelled(true); + ItemStack resultStack = event.getRecipe().getResult(); + ItemStack equipmentItem = null; + ItemStack essenceStack = null; - Player player = (Player) event.getWhoClicked(); - double effectiveCraftLevel = PlayerDataUtil - .getEffectiveLifeSkill(player, LifeSkillType.CRAFTING, true); - List essenceStats = new ArrayList<>(); - ItemStack baseItem = null; - int highestEssLevel = 0; - double totalEssenceLevel = 0; for (ItemStack is : event.getInventory().getMatrix()) { + if (!(essenceStack == null || equipmentItem == null)) { + break; + } if (is == null || is.getType() == Material.AIR) { continue; } ItemStack loopItem = new ItemStack(is); - if (isEssence(loopItem)) { - if (getEssenceMaterial(loopItem) != resultStack.getType()) { - sendMessage(player, plugin.getSettings().getString("language.craft.wrong-ess-type", "")); - player.playSound(player.getEyeLocation(), Sound.BLOCK_LAVA_POP, 0.7F, 0.5F); - return; - } - int essLevel = getEssenceLevel(loopItem); - totalEssenceLevel += essLevel; - highestEssLevel = Math.max(essLevel, highestEssLevel); - essenceStats.add(getEssenceStat(loopItem)); - continue; - } if (is.getType() == resultStack.getType()) { - baseItem = loopItem; + equipmentItem = loopItem; continue; } - System.out.println("ERROR! SOMETHING IS UP WITH ESSENCE CRAFTING!"); + if (isEssence(loopItem)) { + essenceStack = loopItem; + } + } + + if (essenceStack == null || equipmentItem == null) { return; } - if (baseItem == null) { + + if (getEssenceTier(essenceStack) != MaterialUtil.getTierFromStack(equipmentItem)) { + event.getInventory().getResult().setType(Material.BARRIER); + event.getInventory().getResult().setItemMeta(wrongTypeMeta); return; } - List lore = ItemStackExtensionsKt.getLore(baseItem); + + List lore = ItemStackExtensionsKt.getLore(equipmentItem); List strippedLore = stripColor(lore); - int itemLevel = NumberUtils - .toInt(CharMatcher.digit().or(CharMatcher.is('-')).negate().collapseFrom( - ChatColor.stripColor(strippedLore.get(0)), ' ').trim()); - if (highestEssLevel > itemLevel) { - sendMessage(player, plugin.getSettings().getString("language.craft.item-too-low", "")); - player.playSound(player.getEyeLocation(), Sound.BLOCK_LAVA_POP, 0.7F, 0.5F); + + if (!lore.contains(CraftingListener.ESSENCE_SLOT_TEXT)) { + event.getInventory().getResult().setType(Material.BARRIER); + event.getInventory().getResult().setItemMeta(noSlotsMeta); return; } - if (!lore.contains(CraftingListener.ESSENCE_SLOT_TEXT)) { - sendMessage(player, plugin.getSettings().getString("language.craft.no-slots", "")); - player.playSound(player.getEyeLocation(), Sound.BLOCK_LAVA_POP, 0.7F, 0.5F); + + int itemLevel = NumberUtils.toInt(CharMatcher.digit().or(CharMatcher.is('-')).negate() + .collapseFrom(ChatColor.stripColor(strippedLore.get(0)), ' ').trim()); + + int essenceLevel = getEssenceLevel(essenceStack); + + Player player = (Player) event.getViewers().get(0); + int craftingLevel = PlayerDataUtil.getLifeSkillLevel(player, LifeSkillType.CRAFTING); + double levelAdvantage = DeconstructListener.getLevelAdvantage(craftingLevel, itemLevel); + if (levelAdvantage < 0) { + event.getInventory().getResult().setType(Material.BARRIER); + event.getInventory().getResult().setItemMeta(lowLevelMeta); return; } - List craftedStatTypes = new ArrayList<>(); - for (String str : lore) { - if (str.startsWith(ChatColor.AQUA + "")) { - str = CharMatcher.javaLetter().or(CharMatcher.is(' ')) - .retainFrom(ChatColor.stripColor(str).trim()); - craftedStatTypes.add(str); - } + + if (essenceLevel > itemLevel) { + event.getInventory().getResult().setType(Material.BARRIER); + event.getInventory().getResult().setItemMeta(powerfulEssenceMeta); + return; } - for (String str : essenceStats) { - str = CharMatcher.javaLetter().or(CharMatcher.is(' ')) - .retainFrom(ChatColor.stripColor(str).trim()); - if (craftedStatTypes.contains(str)) { - sendMessage(player, plugin.getSettings().getString("language.craft.stat-exists", "")); - player.playSound(player.getEyeLocation(), Sound.BLOCK_LAVA_POP, 0.7F, 0.5F); - return; + + List existingCraftStatStrings = new ArrayList<>(); + for (String str : lore) { + if (!str.startsWith(ChatColor.AQUA + "+")) { + continue; } + str = CharMatcher.javaLetter().or(CharMatcher.is(' ')).retainFrom(ChatColor.stripColor(str).trim()); + existingCraftStatStrings.add(str); } - int essenceCount = essenceStats.size(); - - double craftExp = BASE_INFUSE_EXP + (essenceCount * BONUS_ESS_EXP); - craftExp *= 1 + INFUSE_LEVEL_MULT * (totalEssenceLevel / essenceCount); + String essenceStat = getEssenceStat(essenceStack); + String strippedStat = CharMatcher.javaLetter().or(CharMatcher.is(' ')) + .retainFrom(ChatColor.stripColor(essenceStat).trim()); - double forceSuccessChance = INFUSE_BASE_CHANCE * (1 + effectiveCraftLevel / 100); - int selectedSlot = - random.nextDouble() > forceSuccessChance ? random.nextInt(essenceCount) : random.nextInt(8); - if (selectedSlot > essenceCount - 1) { - event.setCurrentItem(baseItem); - plugin.getStrifePlugin().getSkillExperienceManager().addExperience(player, - LifeSkillType.CRAFTING, craftExp, false, false); - sendMessage(player, plugin.getSettings().getString("language.craft.ess-failed", "")); - player.playSound(player.getEyeLocation(), Sound.BLOCK_FIRE_EXTINGUISH, 1F, 0.5F); - event.setCancelled(false); + if (existingCraftStatStrings.contains(strippedStat)) { + event.getInventory().getResult().setType(Material.BARRIER); + event.getInventory().getResult().setItemMeta(dupeStatMeta); return; } + int slotIndex = lore.indexOf(CraftingListener.ESSENCE_SLOT_TEXT); - lore.remove(slotIndex); - lore.add(slotIndex, ChatColor.AQUA + ChatColor.stripColor(essenceStats.get(selectedSlot))); - ItemStackExtensionsKt.setLore(baseItem, lore); + lore.set(slotIndex, ChatColor.AQUA + ChatColor.stripColor(essenceStat)); + ItemStackExtensionsKt.setLore(equipmentItem, lore); - event.setCurrentItem(baseItem); - craftExp *= INFUSE_SUCCESS_MULT; - plugin.getStrifePlugin().getSkillExperienceManager().addExperience(player, - LifeSkillType.CRAFTING, craftExp, false, false); - sendMessage(player, plugin.getSettings().getString("language.craft.ess-success", "")); - player.playSound(player.getEyeLocation(), Sound.BLOCK_FIRE_EXTINGUISH, 1F, 1.5F); - player.playSound(player.getEyeLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1F, 0.7F); - event.setCancelled(false); + event.getInventory().getResult().setType(equipmentItem.getType()); + event.getInventory().getResult().setItemMeta(equipmentItem.getItemMeta()); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onCraftBarrier(CraftItemEvent event) { + if (event.getCurrentItem() != null && event.getCurrentItem().getType() == Material.BARRIER + || event.getCursor() != null && event.getCursor().getType() == Material.BARRIER) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onEssenceInfuse(CraftItemEvent event) { + if (event.isCancelled()) { + return; + } + if (!ItemStackExtensionsKt.getDisplayName(event.getRecipe().getResult()) + .equals(EquipmentRecipeBuilder.INFUSE_NAME)) { + return; + } + plugin.getStrifePlugin().getSkillExperienceManager().addExperience((Player) event.getWhoClicked(), + LifeSkillType.CRAFTING, 25, false, false); } private boolean isUncraftableByName(String name) { @@ -453,8 +485,7 @@ private boolean isEssence(ItemStack itemStack) { .isBlank(ItemStackExtensionsKt.getDisplayName(itemStack))) { return false; } - if (!ChatColor.stripColor(ItemStackExtensionsKt.getDisplayName(itemStack)) - .equals("Item Essence")) { + if (!ChatColor.stripColor(ItemStackExtensionsKt.getDisplayName(itemStack)).equals("Item Essence")) { return false; } List lore = ItemStackExtensionsKt.getLore(itemStack); @@ -471,21 +502,9 @@ private boolean isEssence(ItemStack itemStack) { return true; } - private Material getEssenceMaterial(ItemStack itemStack) { - String str = ChatColor.stripColor(ItemStackExtensionsKt.getLore(itemStack).get(1)) - .replace("Item Type: ", ""); - if (str.equalsIgnoreCase("Wand")) { - return Material.WOODEN_SWORD; - } - str = str.replace(" ", "_").toUpperCase(); - Material material; - try { - material = Material.getMaterial(str); - } catch (Exception e) { - System.out.println("INVALID MATERIAL ON ESSENCE! What tf is " + str + "?"); - return null; - } - return material; + private Tier getEssenceTier(ItemStack itemStack) { + String str = ChatColor.stripColor(ItemStackExtensionsKt.getLore(itemStack).get(1)).replace("Item Type: ", ""); + return plugin.getTierManager().getTier(str); } private String getEssenceStat(ItemStack itemStack) { diff --git a/src/main/java/info/faceland/loot/managers/LootCraftMatManager.java b/src/main/java/info/faceland/loot/managers/LootCraftMatManager.java index 04836a3f..13554179 100644 --- a/src/main/java/info/faceland/loot/managers/LootCraftMatManager.java +++ b/src/main/java/info/faceland/loot/managers/LootCraftMatManager.java @@ -23,8 +23,10 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Random; import java.util.Set; import org.bukkit.Bukkit; @@ -32,7 +34,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Recipe; import org.bukkit.inventory.ShapedRecipe; -import org.bukkit.inventory.ShapelessRecipe; public final class LootCraftMatManager { @@ -75,15 +76,23 @@ public Material getMaterial(ItemStack stack) { return DeconstructData.getResultMaterial(data, craftMaterials.keySet()); } } + List possibleMaterials = new ArrayList<>(); - for (Recipe recipe : Bukkit.getServer().getRecipesFor(stack)) { - if (recipe instanceof ShapelessRecipe) { - continue; + Iterator it = Bukkit.getServer().recipeIterator(); + while (it.hasNext()) { + Recipe recipe; + try { + recipe = it.next(); + } catch (NoSuchElementException e) { + // THIS IS HORRIBLE, BUT SPIGOT HAS MADE AN ITERATOR INCOMPETENT BEYOND + // MY EXPERIENCE LEVEL, THAT CAN RETURN NoSuchElement EVEN WITHIN A .hasNext() + // WHILE LOOP... MAY GOD HAVE MERCY ON OUR SOULS + break; } - if (recipe instanceof ShapedRecipe) { + if (recipe.getResult().getType() == stack.getType() && recipe instanceof ShapedRecipe) { ShapedRecipe shaped = (ShapedRecipe) recipe; for (ItemStack i : shaped.getIngredientMap().values()) { - if (i == null) { + if (i == null || i.getType() == Material.AIR) { continue; } if (getCraftMaterials().keySet().contains(i.getType())) { diff --git a/src/main/java/info/faceland/loot/managers/StatManager.java b/src/main/java/info/faceland/loot/managers/StatManager.java index df0c7f95..12b6e956 100644 --- a/src/main/java/info/faceland/loot/managers/StatManager.java +++ b/src/main/java/info/faceland/loot/managers/StatManager.java @@ -40,25 +40,38 @@ public Map getLoadedStats() { return itemStats; } - public StatResponse getFinalStat(ItemStat itemStat, double level, double rarity, - boolean special) { + public StatResponse getFinalStat(ItemStat itemStat, double level, double rarity, boolean special) { + return getFinalStat(itemStat, level, rarity, special, RollStyle.RANDOM); + } + + public StatResponse getFinalStat(ItemStat itemStat, double level, double rarity, boolean special, RollStyle style) { StatResponse response = new StatResponse(); - double statRoll; - float baseRollMultiplier; - if (itemStat.getMinBaseValue() == itemStat.getMaxBaseValue()) { - statRoll = itemStat.getMinBaseValue(); - baseRollMultiplier = 0; + double statValue; + float statRoll; + if (itemStat.getMinBaseValue() >= itemStat.getMaxBaseValue()) { + statValue = itemStat.getMinBaseValue(); + statRoll = 0; } else { - baseRollMultiplier = (float) Math.pow(random.nextDouble(), 2.5); - statRoll = - itemStat.getMinBaseValue() + baseRollMultiplier * (itemStat.getMaxBaseValue() - itemStat - .getMinBaseValue()); + switch (style) { + case MAX: + statRoll = 1; + break; + case MIN: + statRoll = 0; + break; + case RANDOM: + default: + statRoll = (float) Math.pow(random.nextDouble(), 2.5); + } + statValue = itemStat.getMinBaseValue() + statRoll * (itemStat.getMaxBaseValue() - itemStat.getMinBaseValue()); } - response.setStatRoll(baseRollMultiplier); + response.setStatRoll(statRoll); + + statValue += level * itemStat.getPerLevelIncrease(); + statValue += rarity * itemStat.getPerRarityIncrease(); - statRoll += itemStat.getPerLevelIncrease() * level + itemStat.getPerRarityIncrease() * rarity; - statRoll *= - 1 + itemStat.getPerLevelMultiplier() * level + itemStat.getPerRarityMultiplier() * rarity; + double multiplier = 1 + (level * itemStat.getPerLevelMultiplier()) + (rarity * itemStat.getPerRarityMultiplier()); + statValue *= multiplier; TextComponent component = new TextComponent(); component.setItalic(false); @@ -67,17 +80,23 @@ public StatResponse getFinalStat(ItemStat itemStat, double level, double rarity, component.setObfuscated(true); } else { if (StringUtils.isNotBlank(itemStat.getStatPrefix())) { - if (baseRollMultiplier >= 0.9) { + if (statRoll >= 0.9) { component.setColor(ChatColor.of(itemStat.getPerfectStatPrefix())); } else { component.setColor(ChatColor.of(itemStat.getStatPrefix())); } } else { - component.setColor(InventoryUtil.getRollColor(itemStat, baseRollMultiplier)); + double roll = statRoll; + if (roll < 0.92) { + roll = Math.max(0, (roll - 0.5) * 2); + } else { + roll = 1; + } + component.setColor(InventoryUtil.getRollColor(itemStat, roll)); } } - String value = Integer.toString((int) statRoll); + String value = Integer.toString((int) statValue); String statString = itemStat.getStatString().replace("{}", value); component.setText(statString); response.setStatString(component.toLegacyText()); @@ -89,25 +108,9 @@ public StatResponse getFinalStat(ItemStat itemStat, double level, double rarity, return response; } - public String getMinStat(ItemStat itemStat, double level, double rarity) { - double statRoll = itemStat.getMinBaseValue(); - statRoll += itemStat.getPerLevelIncrease() * level + itemStat.getPerRarityIncrease() * rarity; - statRoll *= - 1 + itemStat.getPerLevelMultiplier() * level + itemStat.getPerRarityMultiplier() * rarity; - String returnString = itemStat.getStatPrefix(); - returnString = returnString + itemStat.getStatString(); - String value = Integer.toString((int) statRoll); - return returnString.replace("{}", value); - } - - public String getMaxStat(ItemStat itemStat, double level, double rarity) { - double statRoll = itemStat.getMaxBaseValue(); - statRoll += itemStat.getPerLevelIncrease() * level + itemStat.getPerRarityIncrease() * rarity; - statRoll *= - 1 + itemStat.getPerLevelMultiplier() * level + itemStat.getPerRarityMultiplier() * rarity; - String returnString = itemStat.getStatPrefix(); - returnString = returnString + itemStat.getStatString(); - String value = Integer.toString((int) statRoll); - return returnString.replace("{}", value); + public enum RollStyle { + MAX, + MIN, + RANDOM } } diff --git a/src/main/java/info/faceland/loot/menu/upgrade/EnchantMenu.java b/src/main/java/info/faceland/loot/menu/upgrade/EnchantMenu.java index 249ce9a3..a793fbf1 100644 --- a/src/main/java/info/faceland/loot/menu/upgrade/EnchantMenu.java +++ b/src/main/java/info/faceland/loot/menu/upgrade/EnchantMenu.java @@ -1,20 +1,18 @@ /** * The MIT License Copyright (c) 2015 Teal Cube Games - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - * associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package info.faceland.loot.menu.upgrade; @@ -26,9 +24,12 @@ import info.faceland.loot.enchantments.EnchantmentTome; import info.faceland.loot.items.prefabs.ArcaneEnhancer; import info.faceland.loot.items.prefabs.PurifyingScroll; +import info.faceland.loot.managers.StatManager.RollStyle; import info.faceland.loot.menu.BlankIcon; import info.faceland.loot.utils.MaterialUtil; import info.faceland.loot.utils.NumberUtil; +import io.pixeloutlaw.minecraft.spigot.garbage.ListExtensionsKt; +import io.pixeloutlaw.minecraft.spigot.garbage.StringExtensionsKt; import io.pixeloutlaw.minecraft.spigot.hilt.ItemStackExtensionsKt; import java.text.DecimalFormat; import java.util.ArrayList; @@ -202,13 +203,13 @@ private void updateConfirmIcon(Player player) { confirmIcon.getIcon().setType(Material.BARRIER); List lore = new ArrayList<>(); if (selectedEquipment == null || selectedEquipment.getType() == Material.AIR) { - confirmIcon.setDisplayName(TextUtils.color("&eNo Equipment Item...")); + confirmIcon.setDisplayName(StringExtensionsKt.chatColorize("&eNo Equipment Item...")); lore.addAll(noEquipmentLore); ItemStackExtensionsKt.setLore(confirmIcon.getIcon(), lore); return; } if (selectedUpgradeItem == null || selectedUpgradeItem.getType() == Material.AIR) { - confirmIcon.setDisplayName(TextUtils.color("&eNo Upgrade Item...")); + confirmIcon.setDisplayName(StringExtensionsKt.chatColorize("&eNo Upgrade Item...")); lore.addAll(noUpgradeItemLore); ItemStackExtensionsKt.setLore(confirmIcon.getIcon(), lore); return; @@ -249,37 +250,49 @@ private void updateConfirmIcon(Player player) { confirmIcon.getIcon().setType(Material.NETHER_STAR); EnchantmentTome tome = MaterialUtil.getEnchantmentItem(selectedUpgradeItem); + if (StringUtils.isNotBlank(tome.getStat())) { int itemLevel = MaterialUtil.getLevelRequirement(selectedEquipment); - double enchantLevel = PlayerDataUtil - .getEffectiveLifeSkill(player, LifeSkillType.ENCHANTING, true); + double enchantLevel = PlayerDataUtil.getEffectiveLifeSkill(player, LifeSkillType.ENCHANTING, true); double effectiveLevel = Math.max(1, Math.min(enchantLevel, itemLevel)); ItemStat stat = LootPlugin.getInstance().getStatManager().getStat(tome.getStat()); double rarityBonus = MaterialUtil.getBaseEnchantBonus(enchantLevel); String minStat = ChatColor.stripColor( - TextUtils - .color((plugin.getStatManager().getMinStat(stat, effectiveLevel, rarityBonus)))); - String maxStat = ChatColor.stripColor(TextUtils - .color(plugin.getStatManager().getMaxStat(stat, effectiveLevel, 1 + rarityBonus))); + (plugin.getStatManager().getFinalStat(stat, itemLevel, rarityBonus, false, RollStyle.MIN)).getStatString()); + String maxStat = ChatColor.stripColor( + (plugin.getStatManager().getFinalStat(stat, itemLevel, rarityBonus, false, RollStyle.MAX)).getStatString()); + for (String s : validEnchantLore) { lore.add(s.replace("{min}", minStat).replace("{max}", maxStat)); } + + lore.add(""); + lore.add("&bEnchantment Power: &f" + Math.min(itemLevel, (int) effectiveLevel)); + lore.add("&7 Determines max/min enchant"); + lore.add("&7 values! This number is the"); + lore.add("&7 lowest between your enchant"); + lore.add("&7 skill and the item's level."); + lore.add(""); + lore.add("&dEnchantment Bonus: &f+" + rarityBonus * 100 + "%"); + lore.add("&7 Extra power based on your"); + lore.add("&7 enchanting skill, applied"); + lore.add("&7 after all other numbers!"); } + if (!tome.getEnchantments().isEmpty()) { - lore.add(TextUtils.color("&fApplied Enchantments:")); + lore.add("&fApplied Enchantments:"); for (Enchantment enchantment : tome.getEnchantments().keySet()) { - lore.add(TextUtils.color(" &9" + WordUtils.capitalizeFully(enchantment.getKey() - .getKey()) + " " + NumberUtil.toRoman(tome.getEnchantments().get(enchantment)))); + lore.add(" &9" + WordUtils.capitalizeFully(enchantment.getKey().getKey()) + " " + NumberUtil + .toRoman(tome.getEnchantments().get(enchantment))); } } - ItemStackExtensionsKt.setLore(confirmIcon.getIcon(), lore); + ItemStackExtensionsKt.setLore(confirmIcon.getIcon(), ListExtensionsKt.chatColorize(lore)); return; } if (MaterialUtil.isExtender(selectedUpgradeItem)) { - if (!MaterialUtil - .canBeExtended(new ArrayList<>(ItemStackExtensionsKt.getLore(selectedEquipment)))) { + if (!MaterialUtil.canBeExtended(new ArrayList<>(ItemStackExtensionsKt.getLore(selectedEquipment)))) { confirmIcon.setDisplayName(invalidExtend); lore.addAll(invalidExtendLore); ItemStackExtensionsKt.setLore(confirmIcon.getIcon(), lore); @@ -360,21 +373,23 @@ private void updateConfirmIcon(Player player) { itemPlus += 1; } itemPlus = Math.min(itemPlus, 15); - double successChance = Math.min(100, 100 * MaterialUtil.getSuccessChance(player, itemPlus, - selectedUpgradeItem, scroll)); + double successChance = Math.min(100, 100 * MaterialUtil.getSuccessChance(player, itemPlus, selectedUpgradeItem, scroll)); double maxDura = selectedEquipment.getType().getMaxDurability(); + double damage; + if (maxDura <= 1) { + maxDura = 100; + damage = 0; + } else { + damage = selectedEquipment.getDurability(); + + } double maxPercent = MaterialUtil.getMaxFailureDamagePercent(scroll, itemPlus); double maxDamage = maxDura * maxPercent; - double damage = selectedEquipment.getDurability(); double killChance = 0; double damageChance = 0; if (successChance < 99.9) { double failChance = 100 - successChance; - if (maxDura <= 1) { - killChance = Math.max(0, maxPercent - 1) * 100; - } else { - killChance = failChance * Math.max(0, ((damage + maxDamage) - maxDura) / maxDamage); - } + killChance = failChance * Math.max(0, ((damage + maxDamage) - maxDura) / maxDamage); damageChance = failChance - killChance; } diff --git a/src/main/java/info/faceland/loot/recipe/EquipmentRecipeBuilder.java b/src/main/java/info/faceland/loot/recipe/EquipmentRecipeBuilder.java index e524d47a..c609f2e1 100644 --- a/src/main/java/info/faceland/loot/recipe/EquipmentRecipeBuilder.java +++ b/src/main/java/info/faceland/loot/recipe/EquipmentRecipeBuilder.java @@ -1,8 +1,11 @@ package info.faceland.loot.recipe; -import com.tealcube.minecraft.bukkit.TextUtils; import info.faceland.loot.LootPlugin; +import io.pixeloutlaw.minecraft.spigot.garbage.StringExtensionsKt; import io.pixeloutlaw.minecraft.spigot.hilt.ItemStackExtensionsKt; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -11,16 +14,14 @@ import org.bukkit.inventory.ShapelessRecipe; import org.bukkit.inventory.meta.ItemMeta; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - public class EquipmentRecipeBuilder { public static final String INFUSE_NAME = ChatColor.AQUA + "Item Essence Infusion"; + + private final LootPlugin plugin; + private static List MATERIAL_LIST; private static List INFUSE_LORE; - private LootPlugin plugin; public EquipmentRecipeBuilder(LootPlugin plugin) { this.plugin = plugin; @@ -30,13 +31,11 @@ public EquipmentRecipeBuilder(LootPlugin plugin) { public void setupAllRecipes() { for (Material m : MATERIAL_LIST) { - for(int i=0; i<8; i++) { - setupEssenceRecipe(m, i); - } + setupEssenceRecipe(m); } } - private void setupEssenceRecipe(Material material, int index) { + private void setupEssenceRecipe(Material material) { ItemStack itemStack = new ItemStack(material); ItemStackExtensionsKt.setDisplayName(itemStack, INFUSE_NAME); @@ -44,8 +43,8 @@ private void setupEssenceRecipe(Material material, int index) { ItemMeta meta = itemStack.getItemMeta(); meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES); itemStack.setItemMeta(meta); - ShapelessRecipe recipe = new ShapelessRecipe(new NamespacedKey(plugin, material.toString()+"_"+index), itemStack); - recipe.addIngredient(1, material).addIngredient(1 + index, Material.PRISMARINE_SHARD); + ShapelessRecipe recipe = new ShapelessRecipe(new NamespacedKey(plugin, material.toString() + "_ESS"), itemStack); + recipe.addIngredient(1, material).addIngredient(1, Material.PRISMARINE_SHARD); try { plugin.getServer().addRecipe(recipe); } catch (Exception e) { @@ -55,15 +54,15 @@ private void setupEssenceRecipe(Material material, int index) { private List setupInfusionItem() { List lore = new ArrayList<>(); - lore.add(TextUtils.color("&7Clicking this will put an essence")); - lore.add(TextUtils.color("&7from a random craft slot into")); - lore.add(TextUtils.color("&7an open stat slot on your item.")); - lore.add(TextUtils.color("&7")); - lore.add(TextUtils.color("&eYou cannot add duplicate stat")); - lore.add(TextUtils.color("&etypes to the same item.")); - lore.add(TextUtils.color("&7")); - lore.add(TextUtils.color("&cAll essences will be consumed")); - lore.add(TextUtils.color("&cregardless of the outcome.")); + lore.add(StringExtensionsKt.chatColorize("&7Clicking this will put an essence")); + lore.add(StringExtensionsKt.chatColorize("&7from a random craft slot into")); + lore.add(StringExtensionsKt.chatColorize("&7an open stat slot on your item.")); + lore.add(StringExtensionsKt.chatColorize("&7")); + lore.add(StringExtensionsKt.chatColorize("&eYou cannot add duplicate stat")); + lore.add(StringExtensionsKt.chatColorize("&etypes to the same item.")); + lore.add(StringExtensionsKt.chatColorize("&7")); + lore.add(StringExtensionsKt.chatColorize("&cAll essences will be consumed")); + lore.add(StringExtensionsKt.chatColorize("&cregardless of the outcome.")); return lore; } diff --git a/src/main/java/info/faceland/loot/utils/DropUtil.java b/src/main/java/info/faceland/loot/utils/DropUtil.java index a6d13cff..254ba45c 100644 --- a/src/main/java/info/faceland/loot/utils/DropUtil.java +++ b/src/main/java/info/faceland/loot/utils/DropUtil.java @@ -34,7 +34,6 @@ import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.EntityType; import org.bukkit.entity.Item; import org.bukkit.entity.Player; @@ -136,8 +135,7 @@ public static void dropLoot(LootDropEvent event) { int qualityBonus = 1; double qualityChance = plugin.getSettings().getDouble("config.random-quality-chance", 0.1); - double multiQualityChance = plugin.getSettings() - .getDouble("config.multi-quality-chance", 0.1); + double multiQualityChance = plugin.getSettings().getDouble("config.multi-quality-chance", 0.1); if (random.nextDouble() <= qualityChance) { while (random.nextDouble() <= multiQualityChance && qualityBonus < 5) { @@ -148,11 +146,10 @@ public static void dropLoot(LootDropEvent event) { int upgradeBonus = 1; double upgradeChance = plugin.getSettings().getDouble("config.random-upgrade-chance", 0.1); - double multiUpgradeChance = plugin.getSettings() - .getDouble("config.multi-upgrade-chance", 0.1); + double multiUpgradeChance = plugin.getSettings().getDouble("config.multi-upgrade-chance", 0.1); if (random.nextDouble() <= upgradeChance) { - while (random.nextDouble() <= multiUpgradeChance && upgradeBonus < 9) { + while (random.nextDouble() <= multiUpgradeChance && upgradeBonus < 15) { upgradeBonus++; } upgradeItem(tierItem, upgradeBonus); @@ -215,14 +212,12 @@ public static void dropLoot(LootDropEvent event) { ItemStack his = new IdentityTome(); dropItem(event.getLocation(), his, killer, false); } - if (random.nextDouble() < dropMultiplier * plugin.getSettings() - .getDouble("config.drops.custom-item", 0D)) { + if (random.nextDouble() < dropMultiplier * plugin.getSettings().getDouble("config.drops.custom-item", 0D)) { CustomItem ci; if (plugin.getSettings().getBoolean("config.beast.beast-mode-activate", false)) { ci = plugin.getCustomItemManager().getRandomCustomItemByLevel(mobLevel); } else { - ci = plugin.getCustomItemManager() - .getRandomCustomItem(true, event.getDistance()); + ci = plugin.getCustomItemManager().getRandomCustomItem(true, event.getDistance()); } ItemStack stack = ci.toItemStack(1); @@ -230,8 +225,7 @@ public static void dropLoot(LootDropEvent event) { int qualityBonus = 1; if (ci.canBeQuality()) { double qualityChance = plugin.getSettings().getDouble("config.random-quality-chance", 0.1); - double multiQualityChance = plugin.getSettings() - .getDouble("config.multi-quality-chance", 0.1); + double multiQualityChance = plugin.getSettings().getDouble("config.multi-quality-chance", 0.1); if (random.nextDouble() <= qualityChance) { while (random.nextDouble() <= multiQualityChance && qualityBonus < 5) { @@ -311,32 +305,15 @@ private static void doUniqueDrops(UniqueLoot uniqueLoot, Location location, Play } } - private static ItemStack upgradeItem(ItemStack his, int upgradeBonus) { - boolean succeed = false; - List lore = ItemStackExtensionsKt.getLore(his); - for (int i = 0; i < lore.size(); i++) { - String s = lore.get(i); - String ss = ChatColor.stripColor(s); - if (!ss.startsWith("+")) { - continue; - } - succeed = true; - String loreLev = CharMatcher.digit().or(CharMatcher.is('-')).retainFrom(ss); - int loreLevel = NumberUtils.toInt(loreLev); - lore.set(i, s.replace("+" + loreLevel, "+" + (loreLevel + upgradeBonus))); - String name = getFirstColor(ItemStackExtensionsKt.getDisplayName(his)) + - ("+" + upgradeBonus) + " " + ItemStackExtensionsKt.getDisplayName(his); - ItemStackExtensionsKt.setDisplayName(his, name); - break; + private static void upgradeItem(ItemStack his, int upgradeBonus) { + int currentLevel = MaterialUtil.getUpgradeLevel(his); + if (his.getType().getMaxDurability() <= 1) { + int upgrade = (int) (Math.ceil((double) upgradeBonus / 3)); + int plusAmount = upgrade * 3; + MaterialUtil.bumpItemPlus(his, currentLevel, upgrade, plusAmount); + } else { + MaterialUtil.bumpItemPlus(his, currentLevel, upgradeBonus, upgradeBonus); } - if (succeed) { - ItemStackExtensionsKt.setLore(his, lore); - if (upgradeBonus > 6) { - his.addUnsafeEnchantment(Enchantment.DURABILITY, 1); - ItemStackExtensionsKt.addItemFlags(his, ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_ENCHANTS); - } - } - return his; } private static ItemStack upgradeItemQuality(ItemStack his, int upgradeBonus) { @@ -352,10 +329,10 @@ private static ItemStack upgradeItemQuality(ItemStack his, int upgradeBonus) { String loreLev = CharMatcher.digit().or(CharMatcher.is('-')).retainFrom(ss); int loreLevel = NumberUtils.toInt(loreLev); lore.set(i, s.replace("+" + loreLevel, "+" + (loreLevel + upgradeBonus))); - String qualityEnhanceName = plugin.getSettings() - .getString("language.quality." + upgradeBonus, ""); - String name = getFirstColor(ItemStackExtensionsKt.getDisplayName(his)) + - qualityEnhanceName + " " + ItemStackExtensionsKt.getDisplayName(his); + String qualityEnhanceName = plugin.getSettings().getString("language.quality." + upgradeBonus, ""); + String name = + getFirstColor(ItemStackExtensionsKt.getDisplayName(his)) + qualityEnhanceName + " " + ItemStackExtensionsKt + .getDisplayName(his); ItemStackExtensionsKt.setDisplayName(his, name); break; } diff --git a/src/main/java/info/faceland/loot/utils/InventoryUtil.java b/src/main/java/info/faceland/loot/utils/InventoryUtil.java index 6d0d340f..dcf85090 100644 --- a/src/main/java/info/faceland/loot/utils/InventoryUtil.java +++ b/src/main/java/info/faceland/loot/utils/InventoryUtil.java @@ -53,11 +53,6 @@ public static net.md_5.bungee.api.ChatColor getRollColor(ItemStat stat, double r public static net.md_5.bungee.api.ChatColor getRollColor(double roll, float minHue, float maxHue, float minSat, float maxSat, float minBright, float maxBright) { - if (roll < 0.92) { - roll = Math.max(0, (roll - 0.5) * 2); - } else { - roll = 1; - } float hue = minHue + (maxHue - minHue) * (float) roll; float saturation = minSat + (maxSat - minSat) * (float) roll; float brightness = minBright + (maxBright - minBright) * (float) roll; diff --git a/src/main/java/info/faceland/loot/utils/MaterialUtil.java b/src/main/java/info/faceland/loot/utils/MaterialUtil.java index ad45c28b..506fbfed 100644 --- a/src/main/java/info/faceland/loot/utils/MaterialUtil.java +++ b/src/main/java/info/faceland/loot/utils/MaterialUtil.java @@ -35,6 +35,7 @@ import info.faceland.loot.items.prefabs.SocketExtender; import info.faceland.loot.math.LootRandom; import info.faceland.loot.tier.Tier; +import io.pixeloutlaw.minecraft.spigot.garbage.ListExtensionsKt; import io.pixeloutlaw.minecraft.spigot.hilt.ItemStackExtensionsKt; import java.util.ArrayList; import java.util.List; @@ -50,6 +51,7 @@ import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; @@ -57,10 +59,10 @@ public final class MaterialUtil { - private static final double BONUS_ESS_MULT = 0.21; - private static final double TOOL_QUALITY_ESS_MULT = 0.06; - private static final double MIN_BONUS_ESS_MULT = 0.08; - private static final double BASE_ESSENCE_MULT = 0.65; + private static final double BONUS_ESS_MULT = 0.3; + private static final double TOOL_QUALITY_ESS_MULT = 0.08; + private static final double MIN_BONUS_ESS_MULT = 0.25; + private static final double BASE_ESSENCE_MULT = 0.3; private static final LootRandom random = new LootRandom(); private static String upgradeFailureMsg; @@ -114,26 +116,29 @@ public static void refreshConfig() { .getString("language.extend.fail", ""); } - public static double getSuccessChance(Player player, int targetPlus, ItemStack scrollStack, - UpgradeScroll scroll) { + public static double getSuccessChance(Player player, int targetPlus, ItemStack scrollStack, UpgradeScroll scroll) { double success = scroll.getBaseSuccess(); success -= scroll.getFlatDecay() * targetPlus; success *= 1 - (scroll.getPercentDecay() * targetPlus); success = Math.pow(success, scroll.getExponent()); success += PlayerDataUtil.getEffectiveLifeSkill(player, LifeSkillType.ENCHANTING, true) * 0.001; if (success <= 1) { - for (String s : ItemStackExtensionsKt.getLore(scrollStack)) { - if (s.startsWith(FAILURE_BONUS)) { - success += (1 - success) * getFailureMod(s); - break; - } - } + success += (1 - success) * getFailureMod(getFailureBonus(scrollStack)); } return success; } - public static double getFailureMod(String failString) { - return 1 - (150D / (150 + MaterialUtil.getDigit(failString))); + public static int getFailureBonus(ItemStack scrollStack) { + for (String s : ItemStackExtensionsKt.getLore(scrollStack)) { + if (s.startsWith(FAILURE_BONUS)) { + return MaterialUtil.getDigit(ChatColor.stripColor(s)); + } + } + return 0; + } + + public static double getFailureMod(double failBonus) { + return 1 - (300D / (300D + failBonus)); } public static double getUpgradeFailureDamagePercent(UpgradeScroll scroll, int itemPlus) { @@ -192,35 +197,41 @@ public static void upgradeItem(Player player, ItemStack scrollStack, ItemStack s if (successChance < random.nextDouble()) { double damagePercentage = getUpgradeFailureDamagePercent(scroll, targetLevel); short damage; + if (stack.getType().getMaxDurability() <= 1) { if (damagePercentage < 1) { sendMessage(player, upgradeItemNoDamageMsg); + int shards = getFailureBonus(scrollStack); + distributeShards(player, shards); return; } damage = 1000; } else { - double currentPercentage = - 1 - ((double) stack.getDurability() / stack.getType().getMaxDurability()); + double currentPercentage = 1 - ((double) stack.getDurability() / stack.getType().getMaxDurability()); if (damagePercentage >= currentPercentage) { damage = stack.getType().getMaxDurability(); } else { damage = stack.getDurability(); - damage += (short) (Math - .floor((currentPercentage - damagePercentage) * (double) stack.getType().getMaxDurability())); + damage += (short) (Math.floor((currentPercentage - damagePercentage) * + (double) stack.getType().getMaxDurability())); } } + if (damage >= stack.getType().getMaxDurability()) { ItemStack clone = stack.clone(); sendMessage(player, upgradeItemDestroyMsg); stack.setAmount(0); player.playSound(player.getEyeLocation(), Sound.ENTITY_ITEM_BREAK, 1F, 1F); + int shards = getFailureBonus(scrollStack); if (itemUpgradeLevel > 5) { - ItemStack shard = ShardOfFailure.build(player.getName()); - shard.setAmount(1 + random.nextIntRange(5, 3 + (int) (Math.pow(itemUpgradeLevel, 1.7) / 3))); - player.getInventory().addItem(shard); + shards += 1 + random.nextIntRange(0, (int) (Math.pow(itemUpgradeLevel, 1.2) / 6)); } + distributeShards(player, shards); InventoryUtil.broadcast(player, clone, upgradeItemDestroyBroadcast); return; + } else { + int shards = getFailureBonus(scrollStack); + distributeShards(player, shards); } stack.setDurability(damage); sendMessage(player, upgradeItemDamageMsg); @@ -241,12 +252,28 @@ public static void upgradeItem(Player player, ItemStack scrollStack, ItemStack s } } - private static void bumpItemPlus(ItemStack stack, int currentLevel, int amount) { + private static void distributeShards(Player player, int amount) { + if (amount > 0) { + ItemStack shard = ShardOfFailure.build(player.getName()); + while (amount > 0) { + ItemStack loopShard = shard.clone(); + loopShard.setAmount(Math.min(amount, 64)); + if (player.getInventory().firstEmpty() != -1) { + player.getInventory().addItem(loopShard); + } else { + Item item = player.getWorld().dropItem(player.getLocation(), loopShard); + item.setOwner(player.getUniqueId()); + } + amount -= 64; + } + } + } + + public static void bumpItemPlus(ItemStack stack, int currentLevel, int amount) { bumpItemPlus(stack, currentLevel, amount, amount); } - private static void bumpItemPlus(ItemStack stack, int currentLevel, int statAmount, - int plusAmount) { + public static void bumpItemPlus(ItemStack stack, int currentLevel, int statAmount, int plusAmount) { String itemName = ItemStackExtensionsKt.getDisplayName(stack); if (StringUtils.isBlank(itemName)) { itemName = stack.getType().toString().replaceAll("_", " "); @@ -361,33 +388,40 @@ public static void enhanceEnchantment(Player player, ItemStack item, ItemStack e MessageUtils.sendMessage(player, "&eThis item cannot be enhanced."); return; } - List lore = new ArrayList<>(); + int index = -1; for (int i = 0; i < ItemStackExtensionsKt.getLore(item).size(); i++) { String string = ItemStackExtensionsKt.getLore(item).get(i); if (!isEnchantBar(string)) { - lore.add(string); continue; } - String enchantmentStatString = ChatColor.stripColor(lore.get(lore.size() - 1)); + index = i; + break; + } + if (index == -1) { + return; + } - int statValue = NumberUtils.toInt(CharMatcher.digit() - .or(CharMatcher.is('-')).retainFrom(enchantmentStatString)); + degradeItemEnchantment(item, player); - int itemLevel = getLevelRequirement(item); - itemLevel = Math.max(1, Math.min(100, itemLevel)); - double enchantingLevel = PlayerDataUtil.getEffectiveLifeSkill(player, - LifeSkillType.ENCHANTING, true); + List lore = new ArrayList<>(ItemStackExtensionsKt.getLore(item)); + String enchantmentStatString = ChatColor.stripColor(lore.get(index - 1)); - double enchantingBonus = Math.min(2.5, Math.max(1, enchantingLevel / itemLevel)); - float enhanceRoll = 0.1f + 0.2f * (float) Math.pow(Math.random(), 1.25); + int statValue = NumberUtils.toInt(CharMatcher.digit().or(CharMatcher.is('-')).retainFrom(enchantmentStatString)); - int newValue = statValue + (int) (statValue * enhanceRoll * enchantingBonus); - newValue++; + int itemLevel = getLevelRequirement(item); + itemLevel = Math.max(1, Math.min(100, itemLevel)); + double enchantingLevel = PlayerDataUtil.getEffectiveLifeSkill(player, + LifeSkillType.ENCHANTING, true); - lore.set(lore.size() - 1, ChatColor.BLUE + enchantmentStatString - .replace(Integer.toString(statValue), Integer.toString(newValue))); - lore.add(string.replace(ChatColor.BLACK + "", ChatColor.DARK_RED + "")); - } + double enchantingBonus = Math.min(2.5, Math.max(1, enchantingLevel / itemLevel)); + float enhanceRoll = 0.1f + 0.2f * (float) Math.pow(Math.random(), 1.25); + + int newValue = statValue + (int) (statValue * enhanceRoll * enchantingBonus); + newValue++; + + lore.set(index - 1, + ChatColor.BLUE + enchantmentStatString.replace(Integer.toString(statValue), Integer.toString(newValue))); + lore.set(index, lore.get(index).replace(ChatColor.BLACK + "", ChatColor.DARK_RED + "")); ItemStackExtensionsKt.setLore(item, lore); enhancer.setAmount(enhancer.getAmount() - 1); StrifePlugin.getInstance().getSkillExperienceManager() @@ -395,6 +429,7 @@ public static void enhanceEnchantment(Player player, ItemStack item, ItemStack e player.playSound(player.getLocation(), Sound.BLOCK_BEACON_POWER_SELECT, 1, 0.8f); } + public static void removeEnchantment(ItemStack item) { if (!MaterialUtil.isEnchanted(item)) { return; @@ -440,18 +475,18 @@ public static boolean isEnchanted(ItemStack stack) { for (String string : ItemStackExtensionsKt.getLore(stack)) { String s = net.md_5.bungee.api.ChatColor.stripColor(string); if (!(s.startsWith("[") && string.endsWith("]") && s.contains("||"))) { - continue; + return true; } - return true; } return false; } public static boolean isArcaneEnchanted(ItemStack stack) { + if (!isEnchanted(stack)) { + return false; + } for (String string : ItemStackExtensionsKt.getLore(stack)) { - String s = net.md_5.bungee.api.ChatColor.stripColor(string); - if (!(s.startsWith("[") && string.endsWith("]") && s.contains("||")) && string.contains( - net.md_5.bungee.api.ChatColor.DARK_RED + "")) { + if (isEnchantBar(string) && string.contains("" + ChatColor.DARK_RED)) { return true; } } @@ -464,37 +499,35 @@ public static void degradeItemEnchantment(ItemStack item, Player player) { } List lore = new ArrayList<>(); for (int i = 0; i < ItemStackExtensionsKt.getLore(item).size(); i++) { - String string = ItemStackExtensionsKt.getLore(item).get(i); - if (!isEnchantBar(string)) { - lore.add(string); + String barString = ItemStackExtensionsKt.getLore(item).get(i); + if (!isEnchantBar(barString)) { + lore.add(barString); continue; } ChatColor incompleteBarColor; int index; - if (string.contains("" + ChatColor.DARK_RED)) { - index = string.indexOf("" + ChatColor.DARK_RED); + if (barString.contains("" + ChatColor.DARK_RED)) { + index = barString.indexOf("" + ChatColor.DARK_RED); incompleteBarColor = ChatColor.DARK_RED; - } else if (string.contains("" + ChatColor.BLACK)) { - index = string.indexOf("" + ChatColor.BLACK); + } else if (barString.contains("" + ChatColor.BLACK)) { + index = barString.indexOf("" + ChatColor.BLACK); incompleteBarColor = ChatColor.BLACK; } else { - index = string.length() - 3; + index = barString.indexOf("]"); incompleteBarColor = ChatColor.BLACK; } - Bukkit.getLogger().warning("boop: " + index); if (index <= 4) { lore.remove(lore.size() - 1); lore.add(ChatColor.BLUE + "(Enchantable)"); - sendMessage(player, LootPlugin.getInstance().getSettings() - .getString("language.enchant.degrade", "")); + sendMessage(player, LootPlugin.getInstance().getSettings().getString("language.enchant.degrade", "")); continue; } else if (index <= 7) { - sendMessage(player, LootPlugin.getInstance().getSettings() - .getString("language.enchant.bar-low", "")); + sendMessage(player, LootPlugin.getInstance().getSettings().getString("language.enchant.bar-low", "")); } - string = string.replace("" + incompleteBarColor, ""); - string = new StringBuilder(string).insert(index - 1, incompleteBarColor + "").toString(); - lore.add(string); + barString = barString.replace("" + incompleteBarColor, ""); + barString = new StringBuilder(barString).insert(index - 1, incompleteBarColor + "").toString(); + barString = barString.replace("|]", "|" + ChatColor.BLUE + "]"); + lore.add(barString); } ItemStackExtensionsKt.setLore(item, lore); } @@ -522,30 +555,28 @@ public static boolean enchantItem(Player player, ItemStack tomeStack, ItemStack int index = strippedLore.indexOf("(Enchantable)"); lore.remove(index); - double enchantLevel = PlayerDataUtil - .getEffectiveLifeSkill(player, LifeSkillType.ENCHANTING, true); + double enchantSkill = PlayerDataUtil.getEffectiveLifeSkill(player, LifeSkillType.ENCHANTING, true); List added = new ArrayList<>(); if (!tome.getLore().isEmpty()) { - added.addAll(TextUtils.color(tome.getLore())); + added.addAll(ListExtensionsKt.chatColorize(tome.getLore())); } if (!StringUtils.isBlank(tome.getStat())) { - double rarity = getBonusMultiplier(enchantLevel); - int itemLevel = MaterialUtil.getLevelRequirement(targetItem); - double eLevel = Math.max(1, Math.min(enchantLevel, itemLevel * 2)); + double eLevel = Math.max(1, Math.min(enchantSkill, itemLevel)); + double rarity = MaterialUtil.getBaseEnchantBonus(enchantSkill); ItemStat stat = LootPlugin.getInstance().getStatManager().getStat(tome.getStat()); added.add(LootPlugin.getInstance().getStatManager().getFinalStat(stat, eLevel, rarity, false).getStatString()); } if (tome.getBar()) { - double bonus = getBonusMultiplier(enchantLevel); - double size = 8 + (25 * bonus); - String bars = IntStream.range(0, (int) size).mapToObj(i -> "|") - .collect(Collectors.joining("")); - added.add(ChatColor.BLUE + "[" + bars + ChatColor.BLACK + "|" + ChatColor.BLUE + "]"); + double skillRatio = Math.min(1, enchantSkill / 100); + double roll = skillRatio * Math.random() + (1 - skillRatio) * Math.pow(Math.random(), 2.5); + double size = 8 + 22 * roll; + String bars = IntStream.range(0, (int) size).mapToObj(i -> "|").collect(Collectors.joining("")); + added.add(ChatColor.BLUE + "[" + bars + "]"); } lore.addAll(index, added); @@ -712,17 +743,18 @@ public static int getQuality(ItemStack stack) { return 0; } - public static ItemStack buildEssence(String type, double itemLevel, double craftLevel, - int toolQuality, List possibleStats, boolean lucky) { - int essLevel = 1 + (int) (itemLevel * 0.85 + random.nextDouble() * itemLevel * 0.125); + public static ItemStack buildEssence(Tier tier, double itemLevel, double craftLevelAdvantage, int toolQuality, + List possibleStats, boolean lucky) { - String statString = ChatColor.stripColor( - possibleStats.get(random.nextInt(possibleStats.size()))); + int essLevel = Math.max(1, (int) (Math.floor(itemLevel) / 10) * 10); + + String statString = ChatColor.stripColor(possibleStats.get(random.nextInt(possibleStats.size()))); int statVal = getDigit(statString); - double toolQualityBonus = rollMult(lucky) * (TOOL_QUALITY_ESS_MULT * toolQuality); - double baseCraftBonus = MIN_BONUS_ESS_MULT * (craftLevel / 100); - double bonusCraftBonus = rollMult(lucky, 1.3) * (BONUS_ESS_MULT * (craftLevel / 100)); + craftLevelAdvantage = Math.min(craftLevelAdvantage, 200); + double toolQualityBonus = TOOL_QUALITY_ESS_MULT * toolQuality; + double baseCraftBonus = MIN_BONUS_ESS_MULT * (craftLevelAdvantage / 200); + double bonusCraftBonus = (BONUS_ESS_MULT * (craftLevelAdvantage / 200)) * rollMult(lucky, 1.3); double essMult = BASE_ESSENCE_MULT + baseCraftBonus + bonusCraftBonus + toolQualityBonus; @@ -734,13 +766,14 @@ public static ItemStack buildEssence(String type, double itemLevel, double craft List esslore = new ArrayList<>(); esslore.add("&fItem Level Requirement: " + essLevel); - esslore.add("&fItem Type: " + type); + esslore.add("&fItem Type: " + tier.getName()); esslore.add("&e" + newStatString); esslore.add("&7&oCraft this together with an"); esslore.add("&7&ounfinished item to have a"); esslore.add("&7&ochance of applying this stat!"); esslore.add("&e[ Crafting Component ]"); - ItemStackExtensionsKt.setLore(shard, TextUtils.color(esslore)); + ItemStackExtensionsKt.setLore(shard, ListExtensionsKt.chatColorize(esslore)); + ItemStackExtensionsKt.setCustomModelData(shard, 501); return shard; } @@ -749,11 +782,9 @@ public static int getUpgradeLevel(ItemStack stack) { return getUpgradeLevel(ItemStackExtensionsKt.getDisplayName(stack)); } - public static int getUpgradeLevel(String name) { name = stripColor(name); - String lev = CharMatcher.digit().or(CharMatcher.is('-')).negate().collapseFrom(name, ' ') - .trim(); + String lev = CharMatcher.digit().or(CharMatcher.is('-')).negate().collapseFrom(name, ' ').trim(); return NumberUtils.toInt(lev.split(" ")[0], 0); } @@ -774,8 +805,7 @@ public static int getLevelRequirement(ItemStack stack) { public static Tier getTierFromStack(ItemStack stack) { String strTier = ""; int data = MaterialUtil.getCustomData(stack); - for (DeconstructData dd : LootPlugin.getInstance().getCraftMatManager() - .getDeconstructDataSet()) { + for (DeconstructData dd : LootPlugin.getInstance().getCraftMatManager().getDeconstructDataSet()) { if (StringUtils.isBlank(dd.getTierName())) { continue; } @@ -831,10 +861,7 @@ private static double rollMult(boolean lucky) { } private static double rollMult(boolean lucky, double exponent) { - if (!lucky) { - return Math.pow(random.nextDouble(), exponent); - } - return random.nextDouble(); + return lucky ? random.nextDouble() : Math.pow(random.nextDouble(), exponent); } public static void applyTierLevelData(ItemStack stack, Tier tier, int level) { @@ -845,24 +872,14 @@ public static void applyTierLevelData(ItemStack stack, Tier tier, int level) { } public static int getCustomData(ItemStack stack) { - if (stack.getItemMeta() == null) { - return -1; - } - if (!stack.getItemMeta().hasCustomModelData()) { + if (stack.getItemMeta() == null || !stack.getItemMeta().hasCustomModelData()) { return -1; } return stack.getItemMeta().getCustomModelData(); } public static double getBaseEnchantBonus(double enchantSkill) { - return enchantSkill * 0.005; - } - - public static double getBonusMultiplier(double enchantSkill) { - double enchantPower = Math.max(0, Math.min(1, enchantSkill / 100)); - double skillRoll = enchantPower * random.nextDouble(); - double dumbLuckRoll = (1 - enchantPower) * Math.pow(random.nextDouble(), 2.5); - return skillRoll + dumbLuckRoll + getBaseEnchantBonus(enchantSkill); + return enchantSkill * 0.0015; } private static boolean isBannedUpgradeMaterial(ItemStack item) {