mirror of
https://gitlab.com/phoenix-dvpmt/mmoitems.git
synced 2025-02-07 12:11:22 +01:00
Significantly polished the Item Updater, and the way StatHistory saves and loads data from Gem Stones.
Gemstones now removable (via this *Unsocket* stat available for consumables)
This commit is contained in:
parent
5eeaba43c7
commit
fde1cdce5e
@ -102,7 +102,6 @@ public class ItemStats {
|
||||
DURABILITY = new ItemDamage(),
|
||||
CUSTOM_MODEL_DATA = new CustomModelData(),
|
||||
MAX_DURABILITY = new MaximumDurability(),
|
||||
DURABILITY_BAR = new DurabilityBar(),
|
||||
WILL_BREAK = new LostWhenBroken(),
|
||||
NAME = new DisplayName(),
|
||||
LORE = new Lore(),
|
||||
@ -191,6 +190,7 @@ public class ItemStats {
|
||||
EQUIP_PRIORITY = new DoubleStat("EQUIP_PRIORITY", VersionMaterial.DIAMOND_HORSE_ARMOR.toMaterial(), "Equip Priority", new String[]{"Sets the level of priority this item has for the", "right click to swap equipped armor feature."}),
|
||||
REQUIRED_BIOMES = new RequiredBiomes(),
|
||||
DROP_ON_DEATH = new DisableDeathDrop(),
|
||||
DURABILITY_BAR = new DurabilityBar(),
|
||||
|
||||
// Permanent Effects
|
||||
PERM_EFFECTS = new PermanentEffects(),
|
||||
@ -218,8 +218,6 @@ public class ItemStats {
|
||||
ITEM_TYPE_RESTRICTION = new ItemTypeRestriction(),
|
||||
MAX_CONSUME = new DoubleStat("MAX_CONSUME", Material.BLAZE_POWDER, "Max Consume", new String[]{"Max amount of usage before", "item disappears."}, new String[]{"consumable"}),
|
||||
SUCCESS_RATE = new SuccessRate(),
|
||||
COMPATIBLE_TYPES = new CompatibleTypes(),
|
||||
COMPATIBLE_IDS = new CompatibleIds(),
|
||||
|
||||
// Crafting Stats
|
||||
CRAFTING = new Crafting(),
|
||||
@ -238,7 +236,11 @@ public class ItemStats {
|
||||
LUTE_ATTACK_EFFECT = new LuteAttackEffectStat(),
|
||||
NOTE_WEIGHT = new DoubleStat("NOTE_WEIGHT", VersionMaterial.MUSIC_DISC_MALL.toMaterial(), "Note Weight", new String[]{"Defines how the projectile cast", "by your lute tilts downwards."}, new String[]{"lute"}),
|
||||
REMOVE_ON_CRAFT = new BooleanStat("REMOVE_ON_CRAFT", Material.GLASS_BOTTLE, "Remove on Craft", new String[]{"If the item should be completely", "removed when used in a recipe,", "or if it should become an", "empty bottle or bucket."}, new String[]{"all"}, Material.POTION, Material.SPLASH_POTION, Material.LINGERING_POTION, Material.MILK_BUCKET, Material.LAVA_BUCKET, Material.WATER_BUCKET),
|
||||
COMPATIBLE_TYPES = new CompatibleTypes(),
|
||||
COMPATIBLE_IDS = new CompatibleIds(),
|
||||
GEM_SOCKETS = new GemSockets(),
|
||||
RANDOM_UNSOCKET = new RandomUnsocket(),
|
||||
//todo CAN_UNSOCKET = new CanUnsocket(),
|
||||
REPAIR = new RepairPower(),
|
||||
REPAIR_TYPE = new RepairType(),
|
||||
KNOCKBACK = new DoubleStat("KNOCKBACK", VersionMaterial.IRON_HORSE_ARMOR.toMaterial(), "Knockback", new String[]{"Using this musket will knock", "the user back if positive."}, new String[]{"musket"}),
|
||||
|
@ -19,6 +19,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Field;
|
||||
@ -116,8 +117,11 @@ public class MMOUtils {
|
||||
return type.equals(PotionEffectType.NIGHT_VISION) || type.equals(PotionEffectType.CONFUSION) ? 260 : type.equals(PotionEffectType.BLINDNESS) ? 140 : 80;
|
||||
}
|
||||
|
||||
public static String getDisplayName(ItemStack item) {
|
||||
return item.hasItemMeta() && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : caseOnWords(item.getType().name().toLowerCase().replace("_", " "));
|
||||
@NotNull public static String getDisplayName(@Nullable ItemStack item) {
|
||||
if (item == null) { return "null"; }
|
||||
return (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) ?
|
||||
item.getItemMeta().getDisplayName() :
|
||||
caseOnWords(item.getType().name().toLowerCase().replace("_", " "));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@ import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -39,7 +40,7 @@ public class Consumable extends UseItem {
|
||||
* @param target The item on which the consumable is being applied
|
||||
* @return If the consumable was successfully applied on the item
|
||||
*/
|
||||
public boolean useOnItem(InventoryClickEvent event, NBTItem target) {
|
||||
public boolean useOnItem(@NotNull InventoryClickEvent event, @NotNull NBTItem target) {
|
||||
if (event.getClickedInventory() != event.getWhoClicked().getInventory())
|
||||
return false;
|
||||
|
||||
|
@ -21,6 +21,7 @@ import net.Indyuce.mmoitems.stat.data.type.StatData;
|
||||
import net.Indyuce.mmoitems.stat.type.GemStoneStat;
|
||||
import net.Indyuce.mmoitems.stat.type.ItemStat;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import net.Indyuce.mmoitems.stat.type.StatHistory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Sound;
|
||||
@ -29,6 +30,8 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class GemStone extends UseItem {
|
||||
|
||||
public GemStone(Player player, NBTItem item) {
|
||||
@ -94,31 +97,75 @@ public class GemStone extends UseItem {
|
||||
*/
|
||||
LiveMMOItem gemMMOItem = new LiveMMOItem(getNBTItem());
|
||||
GemstoneData gemData = new GemstoneData(gemMMOItem, foundSocketColor);
|
||||
sockets.apply(gemType, gemData);
|
||||
//UPGRD//MMOItems. Log("Applying Gemstone: \u00a73" + foundSocketColor);
|
||||
|
||||
/*
|
||||
* Now must apply the gem sockets data to the Stat History and then recalculate.
|
||||
*
|
||||
* Gotta, however, find the correct StatData to which apply it to. Damn this can
|
||||
* be pretty complicated!
|
||||
*/
|
||||
StatHistory gemStory = StatHistory.from(targetMMO, ItemStats.GEM_SOCKETS);
|
||||
|
||||
// Original?
|
||||
if (((GemSocketsData) gemStory.getOriginalData()).getEmptySocket(gemType) != null) {
|
||||
//UPGRD//MMOItems.log("\u00a77Applied Gemstone @\u00a76Original\u00a77: \u00a73" + foundSocketColor);
|
||||
|
||||
// Charmer
|
||||
((GemSocketsData) gemStory.getOriginalData()).apply(gemType, gemData);
|
||||
|
||||
} else {
|
||||
|
||||
// Check gem gems lol
|
||||
boolean success = false;
|
||||
for (UUID registeredGem : gemStory.getAllGemstones()) {
|
||||
|
||||
// Get that gem
|
||||
GemSocketsData registeredGemData = (GemSocketsData) gemStory.getGemstoneData(registeredGem);
|
||||
if (registeredGemData == null) { continue; }
|
||||
|
||||
if (registeredGemData.getEmptySocket(gemType) != null) {
|
||||
//UPGRD//MMOItems.log("\u00a77Applied Gemstone @\u00a76Gemstone\u00a77: \u00a73" + foundSocketColor);
|
||||
|
||||
// Charmer
|
||||
success = true;
|
||||
registeredGemData.apply(gemType, gemData); break; } }
|
||||
|
||||
if (!success) {
|
||||
|
||||
for (StatData extraneousGem : gemStory.getExternalData()) {
|
||||
|
||||
// Get that gem
|
||||
GemSocketsData registeredGemData = (GemSocketsData) extraneousGem;
|
||||
if (registeredGemData == null) { continue; }
|
||||
|
||||
if (registeredGemData.getEmptySocket(gemType) != null) {
|
||||
//UPGRD//MMOItems.log("\u00a77Applied Gemstone @\u00a76External\u00a77: \u00a73" + foundSocketColor);
|
||||
|
||||
// Charmer
|
||||
registeredGemData.apply(gemType, gemData); break; } } } }
|
||||
|
||||
// Recalculate
|
||||
targetMMO.setData(ItemStats.GEM_SOCKETS, gemStory.recalculate(targetMMO.getUpgradeLevel()));
|
||||
//UPGRD//MMOItems.log("Applied Gemstone: \u00a73" + foundSocketColor);
|
||||
|
||||
/*
|
||||
* Get the item's level, important for the GemScalingStat
|
||||
*/
|
||||
Integer levelIdentified = null; String scaling = GemUpgradeScaling.SUBSEQUENT;
|
||||
if (gemMMOItem.hasData(ItemStats.GEM_UPGRADE_SCALING)) { scaling = gemMMOItem.getData(ItemStats.GEM_UPGRADE_SCALING).toString(); }
|
||||
//UPGRD//MMOItems. Log("Scaling Identified: \u00a73" + scaling);
|
||||
//UPGRD//MMOItems.log("Scaling Identified: \u00a73" + scaling);
|
||||
switch (scaling) {
|
||||
case GemUpgradeScaling.HISTORIC:
|
||||
levelIdentified = 0;
|
||||
break;
|
||||
case GemUpgradeScaling.SUBSEQUENT:
|
||||
StatData upgradeLevel = targetMMO.getData(ItemStats.UPGRADE);
|
||||
if (upgradeLevel != null) { levelIdentified = ((UpgradeData) upgradeLevel).getLevel(); }
|
||||
levelIdentified = targetMMO.getUpgradeLevel();
|
||||
break;
|
||||
case GemUpgradeScaling.NEVER:
|
||||
default:
|
||||
levelIdentified = null;
|
||||
break;
|
||||
}
|
||||
gemData.setLevel(levelIdentified);
|
||||
//UPGRD//MMOItems. Log("Set Level: \u00a7b" + gemData.getLevel());
|
||||
default: break; }
|
||||
|
||||
gemData.setLevel(levelIdentified);
|
||||
//UPGRD//MMOItems.log("Set Level: \u00a7b" + gemData.getLevel());
|
||||
/*
|
||||
* Only applies NON PROPER and MERGEABLE item stats
|
||||
*/
|
||||
@ -132,7 +179,7 @@ public class GemStone extends UseItem {
|
||||
|
||||
// If the data is MERGEABLE
|
||||
if (data instanceof Mergeable) {
|
||||
//GEM////UPGRD//MMOItems. Log("\u00a79>>> \u00a77Gem-Merging \u00a7c" + stat.getNBTPath());
|
||||
//UPGRD//MMOItems.log("\u00a79>>> \u00a77Gem-Merging \u00a7c" + stat.getNBTPath());
|
||||
|
||||
// Merge into it
|
||||
targetMMO.mergeData(stat, data, gemData.getHistoricUUID());
|
||||
|
@ -7,7 +7,6 @@ import net.Indyuce.mmoitems.api.UpgradeTemplate;
|
||||
import net.Indyuce.mmoitems.api.item.ItemReference;
|
||||
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
|
||||
import net.Indyuce.mmoitems.stat.Enchants;
|
||||
import net.Indyuce.mmoitems.stat.GemSockets;
|
||||
import net.Indyuce.mmoitems.stat.data.GemSocketsData;
|
||||
import net.Indyuce.mmoitems.stat.data.GemstoneData;
|
||||
import net.Indyuce.mmoitems.stat.data.UpgradeData;
|
||||
@ -63,31 +62,32 @@ public class MMOItem implements ItemReference {
|
||||
* stored as a GemStone in the history, allowing to be removed from the item with that same UUID.
|
||||
*/
|
||||
public void mergeData(@NotNull ItemStat stat, @NotNull StatData data, @Nullable UUID associatedGemStone) {
|
||||
//GEM//MMOItems. Log("Merging stone stat \u00a76" + stat.getNBTPath() + "\u00a77 into \u00a7c" + getType().getName() + " " + getId());
|
||||
//GEM//MMOItems.log("Merging stone stat \u00a76" + stat.getNBTPath() + "\u00a77 into \u00a7c" + getType().getName() + " " + getId());
|
||||
|
||||
// Do we already have the data?
|
||||
if (data instanceof Mergeable) {
|
||||
//GEM//MMOItems. Log("\u00a7a + \u00a77Mergeable");
|
||||
//GEM//MMOItems.log("\u00a7a + \u00a77Mergeable");
|
||||
|
||||
// Prepare to merge: Gather History (Also initializes the ORIGINAL stats)
|
||||
StatHistory sHistory = StatHistory.from(this, stat);
|
||||
|
||||
// As GemStone or as External?
|
||||
if (associatedGemStone != null) {
|
||||
//GEM//MMOItems. Log(" \u00a79++\u00a77 As Gemstone \u00a7b" + associatedGemStone.toString());
|
||||
//GEM//MMOItems.log(" \u00a79++\u00a77 As Gemstone \u00a7b" + associatedGemStone.toString());
|
||||
|
||||
// As GemStone
|
||||
sHistory.registerGemstoneData(associatedGemStone, data);
|
||||
|
||||
// As External
|
||||
} else {
|
||||
//GEM//MMOItems. Log(" \u00a7c++\u00a77 As External");
|
||||
//GEM//MMOItems.log(" \u00a7c++\u00a77 As External");
|
||||
|
||||
// As External, UUIDless modifier
|
||||
sHistory.registerExternalData(data);
|
||||
}
|
||||
|
||||
// Recalculate
|
||||
//GEM//MMOItems.log(" \u00a76+++\u00a77 Recalculating...");
|
||||
setData(stat, sHistory.recalculate(getUpgradeLevel()));
|
||||
|
||||
// Merging means replacing if it cannot be merged
|
||||
@ -321,38 +321,51 @@ public class MMOItem implements ItemReference {
|
||||
* from calling it much because it completely loads all the stats
|
||||
* of every Gem Stone.
|
||||
*
|
||||
* @see #getColor()
|
||||
* @see #getAsGemColor()
|
||||
*
|
||||
* @return The list of GemStones contained here.
|
||||
*/
|
||||
@NotNull public ArrayList<MMOItem> extractGemstones() {
|
||||
//XTC//MMOItems.log("\u00a73 *\u00a77 Extracting gems from this\u00a7b " + getType() + " " + getId());
|
||||
|
||||
// Found?
|
||||
GemSocketsData thisSocketsData = (GemSocketsData) getData(ItemStats.GEM_SOCKETS);
|
||||
if (thisSocketsData == null) { return new ArrayList<>(); }
|
||||
if (thisSocketsData == null) {
|
||||
//XTC//MMOItems.log("\u00a7a *\u00a77 Clear array - no data");
|
||||
return new ArrayList<>(); }
|
||||
|
||||
// All right, whats all yous data
|
||||
HashMap<UUID, MMOItem> regeneratedGems = new HashMap<>();
|
||||
for (GemstoneData gem : thisSocketsData.getGemstones()) {
|
||||
//XTC//MMOItems.log("\u00a7a *\u00a77 Found gem stone -\u00a7a " + gem.getMMOItemType() + " " + gem.getMMOItemID());
|
||||
|
||||
// Can we generate?
|
||||
MMOItem restored = MMOItems.plugin.getMMOItem(MMOItems.plugin.getType(gem.getMMOItemType()), gem.getMMOItemID());
|
||||
|
||||
// Valid? neat-o
|
||||
if (restored != null) {
|
||||
restored.color = gem.getSocketColor();
|
||||
//XTC//MMOItems.log("\u00a7a *\u00a73>\u00a77 Valid, regenerated \u00a7e" + ((StringData) restored.getData(ItemStats.NAME)));
|
||||
|
||||
restored.asGemColor = gem.getSocketColor();
|
||||
restored.asGemUUID = gem.getHistoricUUID();
|
||||
regeneratedGems.put(gem.getHistoricUUID(), restored);
|
||||
//XTC//MMOItems.log("\u00a7a >\u00a77 Color \u00a7e" + restored.getAsGemColor());
|
||||
//XTC//MMOItems.log("\u00a7a >\u00a77 UUID \u00a7e" + restored.getAsGemUUID().toString());
|
||||
} }
|
||||
//XTC//MMOItems.log("\u00a7b *\u00a77 Regen Size:\u00a79 " + regeneratedGems.values().size());
|
||||
|
||||
// Identify actual attributes
|
||||
for (ItemStat stat : getStats()) {
|
||||
|
||||
// Mergeable right
|
||||
if (!(stat.getClearStatData() instanceof Mergeable)) { continue; }
|
||||
if (!(stat.getClearStatData() instanceof Mergeable)) {
|
||||
continue; }
|
||||
|
||||
// Any stat affected by gems is sure to have a Stat History
|
||||
StatHistory hist = getStatHistory(stat);
|
||||
if (hist == null) { continue; }
|
||||
if (hist == null) {
|
||||
continue; }
|
||||
//XTC//MMOItems.log("\u00a7a *\u00a7c>\u00a7a Found Stat History \u00a79" + stat.getId());
|
||||
|
||||
// Data associated with any of the gems?
|
||||
for (Map.Entry<UUID, MMOItem> gem : regeneratedGems.entrySet()) {
|
||||
@ -360,6 +373,7 @@ public class MMOItem implements ItemReference {
|
||||
// History got gem registered?
|
||||
StatData historicGemData = hist.getGemstoneData(gem.getKey());
|
||||
if (historicGemData == null) { continue;}
|
||||
//XTC//MMOItems.log("\u00a7a *\u00a77 Found data for gem \u00a7e" + gem.getKey());
|
||||
|
||||
// This gemstone had this data... Override.
|
||||
gem.getValue().setData(stat, historicGemData);
|
||||
@ -367,16 +381,54 @@ public class MMOItem implements ItemReference {
|
||||
} }
|
||||
|
||||
// Thats the gemstones we was searching for
|
||||
//XTC//MMOItems.log("\u00a7b *\u00a77 Result Size:\u00a79 " + regeneratedGems.values().size());
|
||||
return new ArrayList<>(regeneratedGems.values());
|
||||
}
|
||||
|
||||
@Nullable String color;
|
||||
@Nullable String asGemColor;
|
||||
@NotNull UUID asGemUUID = UUID.randomUUID();
|
||||
|
||||
/**
|
||||
* @return Supposing this MMOItem is a Gem Stone within an item,
|
||||
* obtained via {@link #extractGemstones()}, then this
|
||||
* will be the color of the slot it occupies.
|
||||
*/
|
||||
@Nullable public String getColor() { return color; }
|
||||
@Nullable public String getAsGemColor() { return asGemColor; }
|
||||
|
||||
/**
|
||||
* @return Supposing this MMOItem is a Gem Stone within an item,
|
||||
* obtained via {@link #extractGemstones()}, then what
|
||||
* was its UUID?
|
||||
*/
|
||||
@NotNull public UUID getAsGemUUID() { return asGemUUID; }
|
||||
|
||||
/**
|
||||
* Deletes this UUID from all Stat Histories.
|
||||
*
|
||||
* @param gemUUID UUID of gem to remove
|
||||
* @param color Color of the gem socket to restore. <code>null</code> to not restore socket.
|
||||
*/
|
||||
public void removeGemStone(@NotNull UUID gemUUID, @Nullable String color) {
|
||||
|
||||
// Get gemstone data
|
||||
if (!hasData(ItemStats.GEM_SOCKETS)) { return; }
|
||||
|
||||
//GEM//MMOItems.log("\u00a7b-\u00a78-\u00a79-\u00a77 Extracting \u00a7e" + gemUUID.toString());
|
||||
StatHistory gemStory = StatHistory.from(this, ItemStats.GEM_SOCKETS);
|
||||
|
||||
/*
|
||||
* We must only find the StatData where this gem resides,
|
||||
* and eventually the StatHistories of the affected stats
|
||||
* will purge themselves from extraneous gems (that are
|
||||
* no longer registered onto the GEM_SOCKETS history).
|
||||
*/
|
||||
if (GemSocketsData.removeGemFrom(((GemSocketsData) gemStory.getOriginalData()), gemUUID, color)) { return; }
|
||||
|
||||
// Attempt gems
|
||||
for (UUID gemDataUUID : gemStory.getAllGemstones()) { if (GemSocketsData.removeGemFrom(((GemSocketsData) gemStory.getGemstoneData(gemDataUUID)), gemUUID, color)) { return; } }
|
||||
|
||||
// Attempt externals
|
||||
for (StatData externalData : gemStory.getExternalData()) { if (GemSocketsData.removeGemFrom(((GemSocketsData) externalData), gemUUID, color)) { return; } }
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
@ -14,7 +14,9 @@ import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
||||
import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
|
||||
import net.Indyuce.mmoitems.stat.DisplayName;
|
||||
import net.Indyuce.mmoitems.stat.Enchants;
|
||||
import net.Indyuce.mmoitems.stat.Lore;
|
||||
import net.Indyuce.mmoitems.stat.RevisionID;
|
||||
import net.Indyuce.mmoitems.stat.data.*;
|
||||
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
|
||||
@ -163,7 +165,27 @@ public class MMOItemReforger {
|
||||
*/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void update(@Nullable RPGPlayer player, @NotNull ReforgeOptions options) {
|
||||
if (options.isRegenerate()) { regenerate(player); return; }
|
||||
|
||||
// Initialize as Volatile, find source template. GemStones require a Live MMOItem though (to correctly load all Stat Histories and sh)
|
||||
loadLiveMMOItem();
|
||||
MMOItemTemplate template = MMOItems.plugin.getTemplates().getTemplate(mmoItem.getType(), mmoItem.getId()); ItemMeta meta = nbtItem.getItem().getItemMeta();
|
||||
if (template == null) { MMOItems.print(null, "Could not find template for $r{0} {1}$b. ", "MMOItems Reforger", mmoItem.getType().toString(), mmoItem.getId()); mmoItem = null; return; }
|
||||
Validate.isTrue(meta != null, FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), "Invalid item meta prevented $f{0}$b from updating.", template.getType().toString() + " " + template.getId()));
|
||||
|
||||
// Skip all this trash and just regenerate completely
|
||||
if (options.isRegenerate()) {
|
||||
// Store all the history of stat proceedings.
|
||||
HashMap<ItemStat, StatHistory> temporalDataHistory = extratStatDataHistory(options);
|
||||
|
||||
/*
|
||||
* Generate fresh MMOItem, with stats that will be set if the chance is too low
|
||||
*/
|
||||
int determinedItemLevel = regenerate(player, template);
|
||||
//UPDT//MMOItems.log("Determined Level: \u00a7e" + determinedItemLevel);
|
||||
|
||||
// Restore stats
|
||||
restorePreRNGStats(temporalDataHistory, options, template, determinedItemLevel);
|
||||
return; }
|
||||
|
||||
/*
|
||||
* Has to store every stat into itemData, then check each stat of
|
||||
@ -178,13 +200,6 @@ public class MMOItemReforger {
|
||||
* 3: If the stat is gone completely, its again a ZERO chance
|
||||
* so it is removed (the updated value of 0 prevailing).
|
||||
*/
|
||||
|
||||
// Initialize as Volatile, find source template. GemStones require a Live MMOItem though (to correctly load all Stat Histories and sh)
|
||||
loadLiveMMOItem();
|
||||
MMOItemTemplate template = MMOItems.plugin.getTemplates().getTemplate(mmoItem.getType(), mmoItem.getId()); ItemMeta meta = nbtItem.getItem().getItemMeta();
|
||||
//noinspection ConstantConditions
|
||||
Validate.isTrue(meta != null, FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), "Invalid item meta prevented $f{0}$b from updating.", template.getType().toString() + " " + template.getId()));
|
||||
|
||||
// Keep name
|
||||
if (options.shouldKeepName()) { keepName(meta); }
|
||||
|
||||
@ -205,22 +220,7 @@ public class MMOItemReforger {
|
||||
if (options.shouldKeepSoulbind() && mmoItem.hasData(ItemStats.SOULBOUND)) { keepSoulbound(); }
|
||||
|
||||
// Store all the history of stat proceedings.
|
||||
HashMap<ItemStat, StatHistory> temporalDataHistory = new HashMap<>();
|
||||
//UPDT//MMOItems.log(" \u00a71 * \u00a77Remembering Stats");
|
||||
for (ItemStat stat : mmoItem.getStats()) {
|
||||
//UPDT//MMOItems.log(" \u00a79 * \u00a77Stat \u00a7f" + stat.getNBTPath());
|
||||
|
||||
// Skip if it cant merge
|
||||
if (!(stat.getClearStatData() instanceof Mergeable)) { continue; }
|
||||
|
||||
StatHistory hist = StatHistory.from(mmoItem, stat);
|
||||
//UPDT//MMOItems.log(" \u00a73 * \u00a77History of \u00a7f" + hist.getItemStat().getNBTPath());
|
||||
|
||||
// Clear externals
|
||||
if (!options.shouldKeepExternalSH()) { hist.getExternalData().clear(); }
|
||||
|
||||
// Get and set
|
||||
temporalDataHistory.put(hist.getItemStat(), hist); }
|
||||
HashMap<ItemStat, StatHistory> temporalDataHistory = extratStatDataHistory(options);
|
||||
|
||||
/*
|
||||
* Generate fresh MMOItem, with stats that will be set if the chance is too low
|
||||
@ -228,15 +228,24 @@ public class MMOItemReforger {
|
||||
int determinedItemLevel = regenerate(player, template);
|
||||
//UPDT//MMOItems.log("Determined Level: \u00a7e" + determinedItemLevel);
|
||||
|
||||
// Restore stats
|
||||
restorePreRNGStats(temporalDataHistory, options, template, determinedItemLevel);
|
||||
|
||||
// Choose enchantments to keep
|
||||
if (options.shouldKeepEnchantments() && ambiguouslyOriginalEnchantmentCache != null) { ambiguouslyOriginalEnchantmentCache.identifyTrueOriginalEnchantments(mmoItem, cachedEnchantments);}
|
||||
}
|
||||
|
||||
void restorePreRNGStats(@NotNull HashMap<ItemStat, StatHistory> backup, @NotNull ReforgeOptions options, @NotNull MMOItemTemplate template, int determinedItemLevel) {
|
||||
|
||||
/*
|
||||
* Extra step: Check every stat history
|
||||
*/
|
||||
int l = mmoItem.getUpgradeLevel();
|
||||
for (ItemStat stat : temporalDataHistory.keySet()) {
|
||||
for (ItemStat stat : backup.keySet()) {
|
||||
//UPDT//MMOItems.log("\u00a7e @\u00a77 " + stat.getId());
|
||||
|
||||
// Get history
|
||||
StatHistory hist = temporalDataHistory.get(stat);
|
||||
StatHistory hist = backup.get(stat);
|
||||
if (hist == null) { continue; }
|
||||
|
||||
// Alr what the template say
|
||||
@ -282,7 +291,7 @@ public class MMOItemReforger {
|
||||
// Make a clear one
|
||||
clear = new StatHistory(mmoItem, stat, finalData);
|
||||
|
||||
// Data arguably fine tbh, just use previous
|
||||
// Data arguably fine tbh, just use previous
|
||||
} else {
|
||||
//UPDT//MMOItems.log("\u00a7a +\u00a77 Acceptable Range --- kept");
|
||||
|
||||
@ -293,8 +302,17 @@ public class MMOItemReforger {
|
||||
} else {
|
||||
//UPDT//MMOItems.log("\u00a7e +\u00a77 Not contained / unmerged --- reroll I suppose");
|
||||
|
||||
// Make a clear one
|
||||
clear = new StatHistory(mmoItem, stat, hist.getOriginalData());
|
||||
// Delete lore
|
||||
if (ItemStats.LORE.equals(stat) || ItemStats.NAME.equals(stat)) {
|
||||
|
||||
// Keep regenerated one
|
||||
clear = new StatHistory(mmoItem, stat, mmoItem.getData(stat));
|
||||
|
||||
} else {
|
||||
|
||||
// Make a clear one
|
||||
clear = new StatHistory(mmoItem, stat, hist.getOriginalData());
|
||||
}
|
||||
}
|
||||
|
||||
// Keep Gemstone and Extraneous data
|
||||
@ -306,9 +324,29 @@ public class MMOItemReforger {
|
||||
mmoItem.setStatHistory(stat, clear);
|
||||
mmoItem.setData(stat, clear.recalculate(false, l));
|
||||
}
|
||||
}
|
||||
|
||||
// Choose enchantments to keep
|
||||
if (options.shouldKeepEnchantments() && ambiguouslyOriginalEnchantmentCache != null) { ambiguouslyOriginalEnchantmentCache.identifyTrueOriginalEnchantments(mmoItem, cachedEnchantments);}
|
||||
@NotNull HashMap<ItemStat, StatHistory> extratStatDataHistory(@NotNull ReforgeOptions options) {
|
||||
HashMap<ItemStat, StatHistory> ret = new HashMap<>();
|
||||
|
||||
//UPDT//MMOItems.log(" \u00a71 * \u00a77Remembering Stats");
|
||||
for (ItemStat stat : mmoItem.getStats()) {
|
||||
//UPDT//MMOItems.log(" \u00a79 * \u00a77Stat \u00a7f" + stat.getNBTPath());
|
||||
|
||||
// Skip if it cant merge
|
||||
if (!(stat.getClearStatData() instanceof Mergeable)) { continue; }
|
||||
|
||||
StatHistory hist = StatHistory.from(mmoItem, stat);
|
||||
//UPDT//MMOItems.log(" \u00a73 * \u00a77History of \u00a7f" + hist.getItemStat().getNBTPath());
|
||||
|
||||
// Clear externals
|
||||
if (!options.shouldKeepExternalSH()) { hist.getExternalData().clear(); }
|
||||
|
||||
// Get and set
|
||||
ret.put(hist.getItemStat(), hist); }
|
||||
|
||||
// Yes
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -420,6 +458,7 @@ public class MMOItemReforger {
|
||||
// Initialize as Volatile, find source template. GemStones require a Live MMOItem though (to correctly load all Stat Histories and sh)
|
||||
if (!options.shouldKeepGemStones() && !options.shouldKeepExternalSH()) { loadVolatileMMOItem(); } else { loadLiveMMOItem(); }
|
||||
MMOItemTemplate template = MMOItems.plugin.getTemplates().getTemplate(mmoItem.getType(), mmoItem.getId()); ItemMeta meta = nbtItem.getItem().getItemMeta();
|
||||
if (template == null) { MMOItems.print(null, "Could not find template for $r{0} {1}$b. ", "MMOItems Reforger", mmoItem.getType().toString(), mmoItem.getId()); mmoItem = null; return; }
|
||||
//noinspection ConstantConditions
|
||||
Validate.isTrue(meta != null, FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), "Invalid item meta prevented $f{0}$b from updating.", template.getType().toString() + " " + template.getId()));
|
||||
|
||||
@ -474,21 +513,30 @@ public class MMOItemReforger {
|
||||
* lines are desirable to keep (Those that start with §7)
|
||||
*/
|
||||
void keepLore() {
|
||||
if (!mmoItem.hasData(ItemStats.LORE)) { return; }
|
||||
cachedLore = extractLore(((StringListData) mmoItem.getData(ItemStats.LORE)).getList());
|
||||
}
|
||||
|
||||
@NotNull ArrayList<String> extractLore(@NotNull List<String> lore) {
|
||||
|
||||
//UPDT//MMOItems.log(" \u00a7d> \u00a77Keeping Lore");
|
||||
ArrayList<String> ret = new ArrayList<>();
|
||||
|
||||
// Examine every element
|
||||
for (String str : ((StringListData) mmoItem.getData(ItemStats.LORE)).getList()) {
|
||||
for (String str : lore) {
|
||||
//UPDT//MMOItems.log(" \u00a7d>\u00a7c-\u00a7e- \u00a77Line:\u00a7f " + str);
|
||||
|
||||
// Does it start with the promised...?
|
||||
if (str.startsWith("\u00a77")) {
|
||||
//UPDT//MMOItems.log(" \u00a72>\u00a7a-\u00a7e- \u00a77Kept");
|
||||
cachedLore.add(str); }
|
||||
ret.add(str); }
|
||||
}
|
||||
|
||||
//UPDT//MMOItems.log(" \u00a7d> \u00a77Result");
|
||||
//UPDT//for (String lr : cachedLore) { //UPDT//MMOItems.log(" \u00a7d + \u00a77" + lr); }
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Step #1: Identify the current (not-null) enchantment data (creates one if missing)
|
||||
|
@ -46,6 +46,8 @@ public enum Message {
|
||||
SKIN_BROKE("Your skin broke while trying to apply it onto your &6#item#&c."),
|
||||
SKIN_REJECTED("A skin has already been applied onto your &6#item#&c!"),
|
||||
SKIN_INCOMPATIBLE("This skin is not compatible with your &6#item#&c!"),
|
||||
RANDOM_UNSOCKET_GEM_TOO_OLD("The gems have bonded strongly with your item. Cannot remove."),
|
||||
RANDOM_UNSOCKET_SUCCESS("&aYou removed &3#gem# &afrom your &6#item#&a!"),
|
||||
|
||||
// soulbound
|
||||
CANT_BIND_ITEM("This item is currently linked to #player# by a Lvl #level# soulbound. You will have to break this soulbound first."),
|
||||
|
@ -183,8 +183,7 @@ public class RecipeManager implements Reloadable {
|
||||
blueprint.deploy(MythicRecipeStation.SMITHING, nk);
|
||||
|
||||
// Remember it
|
||||
if (nk.getValue() != null) { customRecipes.put(nk.getValue(), blueprint); } else { booklessRecipes.add(blueprint);
|
||||
if (book) { MMOItems.print(null, "Cannot register custom smithing recipe for $e{0} {1}$b into crafting book", "Custom Crafting", type.getId(), id);} }
|
||||
if (nk.getValue() != null) { customRecipes.put(nk.getValue(), blueprint); } else { booklessRecipes.add(blueprint); }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,6 +21,7 @@ import net.Indyuce.mmoitems.api.util.message.Message;
|
||||
import net.Indyuce.mmoitems.stat.type.BooleanStat;
|
||||
import net.Indyuce.mmoitems.stat.type.ConsumableItemInteraction;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CanDeconstruct extends BooleanStat implements ConsumableItemInteraction {
|
||||
public CanDeconstruct() {
|
||||
@ -30,7 +31,7 @@ public class CanDeconstruct extends BooleanStat implements ConsumableItemInterac
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleConsumableEffect(InventoryClickEvent event, PlayerData playerData, Consumable consumable, NBTItem target, Type targetType) {
|
||||
public boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, Type targetType) {
|
||||
String itemTierTag = target.getString("MMOITEMS_TIER");
|
||||
if (itemTierTag.equals("") || !consumable.getNBTItem().getBoolean("MMOITEMS_CAN_DECONSTRUCT"))
|
||||
return false;
|
||||
|
@ -30,6 +30,7 @@ import io.lumine.mythic.lib.api.item.ItemTag;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.api.util.SmartGive;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CanDeskin extends BooleanStat implements ConsumableItemInteraction {
|
||||
public CanDeskin() {
|
||||
@ -39,7 +40,7 @@ public class CanDeskin extends BooleanStat implements ConsumableItemInteraction
|
||||
|
||||
// TODO needs some cleanup
|
||||
@Override
|
||||
public boolean handleConsumableEffect(InventoryClickEvent event, PlayerData playerData, Consumable consumable, NBTItem target, Type targetType) {
|
||||
public boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, Type targetType) {
|
||||
String skinId = target.getString("MMOITEMS_SKIN_ID");
|
||||
Player player = playerData.getPlayer();
|
||||
|
||||
|
@ -17,6 +17,7 @@ import net.Indyuce.mmoitems.api.util.message.Message;
|
||||
import net.Indyuce.mmoitems.stat.type.BooleanStat;
|
||||
import net.Indyuce.mmoitems.stat.type.ConsumableItemInteraction;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CanIdentify extends BooleanStat implements ConsumableItemInteraction {
|
||||
public CanIdentify() {
|
||||
@ -25,7 +26,7 @@ public class CanIdentify extends BooleanStat implements ConsumableItemInteractio
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleConsumableEffect(InventoryClickEvent event, PlayerData playerData, Consumable consumable, NBTItem target, Type targetType) {
|
||||
public boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, Type targetType) {
|
||||
if (targetType != null)
|
||||
return false;
|
||||
|
||||
|
74
src/main/java/net/Indyuce/mmoitems/stat/CanUnsocket.java
Normal file
74
src/main/java/net/Indyuce/mmoitems/stat/CanUnsocket.java
Normal file
@ -0,0 +1,74 @@
|
||||
package net.Indyuce.mmoitems.stat;
|
||||
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import net.Indyuce.mmoitems.ItemStats;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.MMOUtils;
|
||||
import net.Indyuce.mmoitems.api.ItemTier;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.event.item.DeconstructItemEvent;
|
||||
import net.Indyuce.mmoitems.api.interaction.Consumable;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import net.Indyuce.mmoitems.api.util.message.Message;
|
||||
import net.Indyuce.mmoitems.stat.data.GemSocketsData;
|
||||
import net.Indyuce.mmoitems.stat.type.BooleanStat;
|
||||
import net.Indyuce.mmoitems.stat.type.ConsumableItemInteraction;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This item will be able to be used on other items, and
|
||||
* pop up an unsocketing GUI if it would make sense.
|
||||
*
|
||||
* @author Gunging
|
||||
*/
|
||||
public class CanUnsocket extends BooleanStat implements ConsumableItemInteraction {
|
||||
public CanUnsocket() {
|
||||
super("CAN_UNSOCKET", Material.PAPER, "Can Unsocket?",
|
||||
new String[] { "This item, when used on another item, if", "that other item has Gem Stones", "may be used to remove those Gems." },
|
||||
new String[] { "consumable" });
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, Type targetType) {
|
||||
|
||||
/*
|
||||
* Cancel if the target is just not an MMOItem
|
||||
*/
|
||||
if (targetType == null) { return false; }
|
||||
|
||||
/*
|
||||
* No Gemstones? No service
|
||||
*/
|
||||
MMOItem mmo = new VolatileMMOItem(target);
|
||||
if (!mmo.hasData(ItemStats.GEM_SOCKETS)) { return false; }
|
||||
GemSocketsData mmoGems = (GemSocketsData) mmo.getData(ItemStats.GEM_SOCKETS);
|
||||
if (mmoGems == null || mmoGems.getGemstones().size() == 0) { return false; }
|
||||
Player player = playerData.getPlayer();
|
||||
|
||||
/*
|
||||
* All right do it correctly I guess.
|
||||
*
|
||||
* Cancel if no gem could be extracted.
|
||||
*/
|
||||
mmo = new LiveMMOItem(target);
|
||||
ArrayList<MMOItem> mmoGemStones = mmo.extractGemstones();
|
||||
if (mmoGemStones.size() == 0) {
|
||||
Message.RANDOM_UNSOCKET_GEM_TOO_OLD.format(ChatColor.YELLOW, "#item#", MMOUtils.getDisplayName(event.getCurrentItem())).send(player);
|
||||
return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -46,7 +46,7 @@ public class DisplayName extends StringStat {
|
||||
String sB4 = suffix.substring(0, lvlOFFSET);
|
||||
String aFt = suffix.substring(lvlOFFSET + "#lvl#".length());
|
||||
String sB4_alt = sB4.replace("+", "-");
|
||||
String aFt_alt = sB4.replace("+", "-");
|
||||
String aFt_alt = aFt.replace("+", "-");
|
||||
|
||||
// Remove it
|
||||
if (format.contains(sB4)) {
|
||||
|
@ -35,7 +35,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class GemSockets extends ItemStat {
|
||||
public GemSockets() {
|
||||
super("GEM_SOCKETS", Material.EMERALD, "Gem Sockets", new String[] { "The amount of gem", "sockets your weapon has." },
|
||||
new String[] { "piercing", "slashing", "blunt", "offhand", "range", "tool", "armor", "accessory" });
|
||||
new String[] { "piercing", "slashing", "blunt", "offhand", "range", "tool", "armor", "accessory", "!gem_stone" });
|
||||
}
|
||||
|
||||
@Override
|
||||
|
141
src/main/java/net/Indyuce/mmoitems/stat/RandomUnsocket.java
Normal file
141
src/main/java/net/Indyuce/mmoitems/stat/RandomUnsocket.java
Normal file
@ -0,0 +1,141 @@
|
||||
package net.Indyuce.mmoitems.stat;
|
||||
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
|
||||
import net.Indyuce.mmoitems.ItemStats;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.MMOUtils;
|
||||
import net.Indyuce.mmoitems.api.ItemTier;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.event.item.DeconstructItemEvent;
|
||||
import net.Indyuce.mmoitems.api.interaction.Consumable;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import net.Indyuce.mmoitems.api.util.message.Message;
|
||||
import net.Indyuce.mmoitems.stat.data.DoubleData;
|
||||
import net.Indyuce.mmoitems.stat.data.GemSocketsData;
|
||||
import net.Indyuce.mmoitems.stat.type.ConsumableItemInteraction;
|
||||
import net.Indyuce.mmoitems.stat.type.DoubleStat;
|
||||
import net.Indyuce.mmoitems.stat.type.StatHistory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* When used on an item with Gem Sockets Data, it will
|
||||
* cause a random gem to pop out.
|
||||
*
|
||||
* @author Gunging
|
||||
*/
|
||||
public class RandomUnsocket extends DoubleStat implements ConsumableItemInteraction {
|
||||
public RandomUnsocket() {
|
||||
super("RANDOM_UNSOCKET", Material.BOWL, "Random Unsocket",
|
||||
new String[] { "Number of gems (rounded down) that", "will pop out of an item when", "this is applied." },
|
||||
new String[] { "consumable" });
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, Type targetType) {
|
||||
|
||||
/*
|
||||
* Cancel if the target is just not an MMOItem
|
||||
*/
|
||||
if (targetType == null) { return false; }
|
||||
|
||||
/*
|
||||
* No Gemstones? No service
|
||||
*/
|
||||
MMOItem mmoVol = new VolatileMMOItem(target);
|
||||
if (!mmoVol.hasData(ItemStats.GEM_SOCKETS)) { return false; }
|
||||
GemSocketsData mmoGems = (GemSocketsData) mmoVol.getData(ItemStats.GEM_SOCKETS);
|
||||
if (mmoGems == null || mmoGems.getGemstones().size() == 0) { return false; }
|
||||
Player player = playerData.getPlayer();
|
||||
|
||||
/*
|
||||
* All right do it correctly I guess.
|
||||
*
|
||||
* Cancel if no gem could be extracted.
|
||||
*/
|
||||
MMOItem mmo = new LiveMMOItem(target);
|
||||
ArrayList<MMOItem> mmoGemStones = mmo.extractGemstones();
|
||||
if (mmoGemStones.size() == 0) {
|
||||
Message.RANDOM_UNSOCKET_GEM_TOO_OLD.format(ChatColor.YELLOW, "#item#", MMOUtils.getDisplayName(event.getCurrentItem())).send(player);
|
||||
return false; }
|
||||
|
||||
// Get removed gems amount
|
||||
int s = 1;
|
||||
if (consumable.getMMOItem().hasData(ItemStats.RANDOM_UNSOCKET)) {
|
||||
|
||||
// Get
|
||||
DoubleData unsocket = (DoubleData) consumable.getMMOItem().getData(ItemStats.RANDOM_UNSOCKET);
|
||||
if (unsocket != null) { s = SilentNumbers.floor(unsocket.getValue()); } }
|
||||
//GEM//for (String str : SilentNumbers.transcribeList(mmoGemStones, (lam) -> "\u00a73Found \u00a77 " + ((MMOItem) lam).getType().getId() + " " + ((MMOItem) lam).getId() )) { MMOItems.log(str); };
|
||||
|
||||
// Drop gemstones to the ground :0
|
||||
ArrayList<ItemStack> items2Drop = new ArrayList<>();
|
||||
while (s > 0 && mmoGemStones.size() > 0) {
|
||||
|
||||
/*
|
||||
* Choose a gem to drop :)
|
||||
*/
|
||||
int randomGem = SilentNumbers.floor(SilentNumbers.randomRange(0, mmoGemStones.size()));
|
||||
if (randomGem >= mmoGemStones.size()) { randomGem = mmoGemStones.size() - 1;}
|
||||
|
||||
// Choose gem
|
||||
MMOItem gem = mmoGemStones.get(randomGem);
|
||||
mmoGemStones.remove(randomGem);
|
||||
//GEM//MMOItems.log("\u00a73 *\u00a77 Chose to remove\u00a7b " + gem.getType() + " " + gem.getId());
|
||||
|
||||
try {
|
||||
|
||||
// Drop?
|
||||
ItemStack builtGem = gem.newBuilder().build();
|
||||
//GEM//MMOItems.log("\u00a73 *\u00a77 Built " + SilentNumbers.getItemName(builtGem));
|
||||
|
||||
// Valid?
|
||||
if (!SilentNumbers.isAir(builtGem)) {
|
||||
|
||||
// Drop
|
||||
items2Drop.add(builtGem);
|
||||
String chosenColor;
|
||||
if (gem.getAsGemColor() != null) {
|
||||
//GEM//MMOItems.log("\u00a7b *\u00a77 Restored slot\u00a7e " + gem.getAsGemColor());
|
||||
chosenColor = gem.getAsGemColor(); } else {
|
||||
//GEM//MMOItems.log("\u00a7b *\u00a77 Restored slot\u00a76 " + GemSocketsData.getUncoloredGemSlot() + " \u00a78(Uncolored Def)");
|
||||
chosenColor = GemSocketsData.getUncoloredGemSlot(); }
|
||||
|
||||
// Unregister
|
||||
mmo.removeGemStone(gem.getAsGemUUID(), chosenColor);
|
||||
|
||||
// Gem Removal Count Decreased
|
||||
s--;
|
||||
|
||||
// Message
|
||||
Message.RANDOM_UNSOCKET_SUCCESS.format(ChatColor.YELLOW, "#item#", MMOUtils.getDisplayName(event.getCurrentItem()), "#gem#", MMOUtils.getDisplayName(builtGem)).send(player);
|
||||
}
|
||||
|
||||
} catch (Throwable e) { MMOItems.print(Level.WARNING, "Could not unsocket gem from item $u{0}$b: $f{1}", "Stat \u00a7eRandom Unsocket", SilentNumbers.getItemName(event.getCurrentItem()), e.getMessage()); }
|
||||
}
|
||||
|
||||
// Replace
|
||||
mmo.setData(ItemStats.GEM_SOCKETS, StatHistory.from(mmo, ItemStats.GEM_SOCKETS).recalculate(mmo.getUpgradeLevel()));
|
||||
//GEM//MMOItems.log("\u00a7b*\u00a77 Final at \u00a7b" + ((GemSocketsData) mmo.getData(ItemStats.GEM_SOCKETS)).getEmptySlots().size() + " Empty\u00a77 and \u00a7e" + ((GemSocketsData) mmo.getData(ItemStats.GEM_SOCKETS)).getGemstones().size() + " Gems");
|
||||
event.setCurrentItem(mmo.newBuilder().build());
|
||||
|
||||
// Give the gems back
|
||||
for (ItemStack drop : player.getInventory().addItem(items2Drop.toArray(new ItemStack[0])).values()) player.getWorld().dropItem(player.getLocation(), drop);
|
||||
player.playSound(player.getLocation(), Sound.BLOCK_IRON_DOOR_OPEN, 1, 2);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@ import net.Indyuce.mmoitems.api.util.message.Message;
|
||||
import net.Indyuce.mmoitems.stat.type.ConsumableItemInteraction;
|
||||
import net.Indyuce.mmoitems.stat.type.DoubleStat;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class RepairPower extends DoubleStat implements ConsumableItemInteraction {
|
||||
public RepairPower() {
|
||||
@ -29,7 +30,7 @@ public class RepairPower extends DoubleStat implements ConsumableItemInteraction
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleConsumableEffect(InventoryClickEvent event, PlayerData playerData, Consumable consumable, NBTItem target, Type targetType) {
|
||||
public boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, Type targetType) {
|
||||
int repairPower = (int) consumable.getNBTItem().getStat(ItemStats.REPAIR.getId());
|
||||
if (repairPower <= 0)
|
||||
return false;
|
||||
|
@ -23,6 +23,7 @@ import net.Indyuce.mmoitems.stat.type.ConsumableItemInteraction;
|
||||
import net.Indyuce.mmoitems.stat.type.DoubleStat;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SoulbindingBreakChance extends DoubleStat implements ConsumableItemInteraction {
|
||||
private static final Random random = new Random();
|
||||
@ -35,7 +36,7 @@ public class SoulbindingBreakChance extends DoubleStat implements ConsumableItem
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleConsumableEffect(InventoryClickEvent event, PlayerData playerData, Consumable consumable, NBTItem target, Type targetType) {
|
||||
public boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, Type targetType) {
|
||||
Player player = playerData.getPlayer();
|
||||
|
||||
double soulboundBreakChance = consumable.getNBTItem().getStat("SOULBOUND_BREAK_CHANCE");
|
||||
|
@ -23,6 +23,7 @@ import net.Indyuce.mmoitems.stat.type.ConsumableItemInteraction;
|
||||
import net.Indyuce.mmoitems.stat.type.DoubleStat;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SoulbindingChance extends DoubleStat implements ConsumableItemInteraction {
|
||||
private static final Random random = new Random();
|
||||
@ -34,7 +35,7 @@ public class SoulbindingChance extends DoubleStat implements ConsumableItemInter
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleConsumableEffect(InventoryClickEvent event, PlayerData playerData, Consumable consumable, NBTItem target, Type targetType) {
|
||||
public boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, Type targetType) {
|
||||
Player player = playerData.getPlayer();
|
||||
|
||||
double soulbindingChance = consumable.getNBTItem().getStat("SOULBINDING_CHANCE");
|
||||
|
@ -170,7 +170,7 @@ public class UpgradeStat extends ItemStat implements ConsumableItemInteraction {
|
||||
public StatData getClearStatData() { return new UpgradeData(null, null, false, false, 0, 0D); }
|
||||
|
||||
@Override
|
||||
public boolean handleConsumableEffect(InventoryClickEvent event, PlayerData playerData, Consumable consumable, NBTItem target, Type targetType) {
|
||||
public boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, Type targetType) {
|
||||
VolatileMMOItem mmoitem = consumable.getMMOItem();
|
||||
Player player = playerData.getPlayer();
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
package net.Indyuce.mmoitems.stat.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import io.lumine.mythic.lib.api.util.Ref;
|
||||
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
|
||||
@ -72,21 +69,20 @@ public class GemSocketsData implements StatData, Mergeable, RandomStatData {
|
||||
*/
|
||||
@Nullable public String getEmptySocket(@NotNull String gem) {
|
||||
for (String slot : emptySlots)
|
||||
if (gem.equals("") || slot.equals(MMOItems.plugin.getConfig().getString("gem-sockets.uncolored")) || gem.equals(slot))
|
||||
if (gem.equals("") || slot.equals(getUncoloredGemSlot()) || gem.equals(slot))
|
||||
return slot;
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull public static String getUncoloredGemSlot() { String s = MMOItems.plugin.getConfig().getString("gem-sockets.uncolored"); return s == null ? "Uncolored" : s; }
|
||||
|
||||
public void add(GemstoneData gem) {
|
||||
gems.add(gem);
|
||||
}
|
||||
|
||||
public void apply(String gem, GemstoneData gemstone) {
|
||||
emptySlots.remove(getEmptySocket(gem));
|
||||
gems.add(gemstone);
|
||||
}
|
||||
public void apply(String gem, GemstoneData gemstone) { emptySlots.remove(getEmptySocket(gem)); gems.add(gemstone); }
|
||||
|
||||
public void addEmptySlot(String slot) {
|
||||
public void addEmptySlot(@NotNull String slot) {
|
||||
emptySlots.add(slot);
|
||||
}
|
||||
|
||||
@ -98,6 +94,47 @@ public class GemSocketsData implements StatData, Mergeable, RandomStatData {
|
||||
return gems;
|
||||
}
|
||||
|
||||
public void removeGem(@NotNull UUID gem) {
|
||||
|
||||
// Find
|
||||
GemstoneData d = null;
|
||||
for (GemstoneData data : getGemstones()) {
|
||||
if (data.getHistoricUUID().equals(gem)) {
|
||||
//GEM//MMOItems.log("\u00a7b*\u00a77 Found gem to unregister: \u00a7a" + data.getName());
|
||||
d = data; break; }}
|
||||
|
||||
// Remove
|
||||
gems.remove(d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes such gem from this GemSocketsData, if it exists.
|
||||
*
|
||||
* @param data The Data from which to remove the gem
|
||||
* @param gemUUID The Gem to remove
|
||||
* @param socket The socket color to replace the gem with, <code>null</code> for no socket.
|
||||
* @return Whether a gem was removed from the data.
|
||||
*/
|
||||
public static boolean removeGemFrom(@NotNull GemSocketsData data, @NotNull UUID gemUUID, @Nullable String socket) {
|
||||
|
||||
boolean removal = false;
|
||||
for (GemstoneData gem : data.getGemstones()) {
|
||||
|
||||
// Is it the one we are searching for?
|
||||
if (gem.getHistoricUUID().equals(gemUUID)) {
|
||||
|
||||
// Found it, restore the socket and we're done.
|
||||
if (socket != null) { data.addEmptySlot(socket); }
|
||||
|
||||
// Remove
|
||||
removal = true; break; } }
|
||||
|
||||
// Its time.
|
||||
if (removal) { data.removeGem(gemUUID); }
|
||||
|
||||
return removal;
|
||||
}
|
||||
|
||||
public JsonObject toJson() {
|
||||
JsonObject object = new JsonObject();
|
||||
|
||||
@ -115,17 +152,29 @@ public class GemSocketsData implements StatData, Mergeable, RandomStatData {
|
||||
@Override
|
||||
public void merge(StatData data) {
|
||||
Validate.isTrue(data instanceof GemSocketsData, "Cannot merge two different stat data types");
|
||||
|
||||
//MRG//MMOItems.log("\u00a73||| \u00a77Merging slots; Original:");
|
||||
//MRG//for (String str : SilentNumbers.transcribeList(emptySlots, (s) -> "\u00a73|+ \u00a77" + ((String) s))) { MMOItems.log(str); }
|
||||
//MRG//MMOItems.log("\u00a73||| \u00a77Including");
|
||||
//MRG//for (String str : SilentNumbers.transcribeList(((GemSocketsData) data).emptySlots, (s) -> "\u00a73|+ \u00a77" + ((String) s))) { MMOItems.log(str); }
|
||||
|
||||
// Combine both actual gems, and empty slots
|
||||
emptySlots.addAll(((GemSocketsData) data).emptySlots);
|
||||
gems.addAll(((GemSocketsData) data).getGemstones());
|
||||
|
||||
//MRG//MMOItems.log("\u00a73||| \u00a7aResult");
|
||||
//MRG//for (String str : SilentNumbers.transcribeList(emptySlots, (s) -> "\u00a73|+ \u00a77" + ((String) s))) { MMOItems.log(str); }
|
||||
//MRG//MMOItems.log("\u00a73||| \u00a7a---------------------------------------");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull StatData cloneData() {
|
||||
|
||||
// Start Fresh
|
||||
GemSocketsData ret = new GemSocketsData(emptySlots);
|
||||
GemSocketsData ret = new GemSocketsData(new ArrayList<>(emptySlots));
|
||||
|
||||
// Add Gems
|
||||
for (GemstoneData g : getGemstones()) { ret.add(g); }
|
||||
for (GemstoneData g : getGemstones()) { ret.add(g.cloneGem()); }
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -20,6 +20,20 @@ public class GemstoneData {
|
||||
@NotNull private final String name;
|
||||
@Nullable Integer levelPut = 0;
|
||||
@NotNull final UUID historicUUID;
|
||||
@Nullable final String mmoitemType;
|
||||
@Nullable final String mmoitemID;
|
||||
@Nullable String socketColor;
|
||||
|
||||
public GemstoneData cloneGem() {
|
||||
|
||||
GemstoneData ret = new GemstoneData(getName(), getMMOItemType(), getMMOItemID(), getSocketColor(), getHistoricUUID());
|
||||
for (AbilityData d : abilities) { ret.addAbility(d); }
|
||||
for (PotionEffectData d : effects) { ret.addPermanentEffect(d); }
|
||||
for (ItemStat d : stats.keySet()) { ret.setStat(d, stats.get(d)); }
|
||||
ret.setLevel(getLevel());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gemstone equals method is for practical purposes and only checks that
|
||||
@ -53,11 +67,6 @@ public class GemstoneData {
|
||||
return socketColor;
|
||||
}
|
||||
|
||||
@Nullable final String mmoitemType;
|
||||
@Nullable final String mmoitemID;
|
||||
@Nullable
|
||||
String socketColor;
|
||||
|
||||
/**
|
||||
* This constructor is not really performance friendly. It should only be
|
||||
* used when applying gem stones to keep max performance.
|
||||
@ -171,11 +180,24 @@ public class GemstoneData {
|
||||
*/
|
||||
public GemstoneData(@NotNull String name, @Nullable String type, @Nullable String id, @Nullable String color) {
|
||||
this.name = name;
|
||||
mmoitemID = type;
|
||||
mmoitemType = id;
|
||||
mmoitemID = id;
|
||||
mmoitemType = type;
|
||||
socketColor = color;
|
||||
historicUUID = UUID.randomUUID();
|
||||
}
|
||||
historicUUID = UUID.randomUUID(); }
|
||||
|
||||
/**
|
||||
* This is a completely empty builder.
|
||||
* <p></p>
|
||||
* You may add whatever you want with <code>addAbility()</code>,<code>addPermamentEffect</code>, or most widely usedly, <code>setStat()</code>.
|
||||
* @param name Name to display in the lore of the item when you put the gemstone into it.
|
||||
* @param color Color of the socket this gem is inserted onto
|
||||
*/
|
||||
public GemstoneData(@NotNull String name, @Nullable String type, @Nullable String id, @Nullable String color, @NotNull UUID uiid) {
|
||||
this.name = name;
|
||||
mmoitemID = id;
|
||||
mmoitemType = type;
|
||||
socketColor = color;
|
||||
historicUUID = uiid; }
|
||||
|
||||
/**
|
||||
* Add an ability to this Gem Stone
|
||||
@ -227,6 +249,7 @@ public class GemstoneData {
|
||||
if (mmoitemID != null) { object.addProperty("Id", mmoitemID); }
|
||||
if (mmoitemType != null) { object.addProperty("Type", mmoitemType); }
|
||||
object.addProperty("Level", levelPut);
|
||||
object.addProperty("Color", socketColor);
|
||||
|
||||
/*
|
||||
* These seem obsolete. Abilities, effects, and stats, are merged into the
|
||||
|
@ -6,6 +6,8 @@ import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.interaction.Consumable;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Stats which implement a consumable action like deconstructing, identifying,
|
||||
@ -29,5 +31,5 @@ public interface ConsumableItemInteraction {
|
||||
* (basically return true if it should be the only
|
||||
* consumable effect applied).
|
||||
*/
|
||||
public boolean handleConsumableEffect(InventoryClickEvent event, PlayerData playerData, Consumable consumable, NBTItem target, Type targetType);
|
||||
boolean handleConsumableEffect(@NotNull InventoryClickEvent event, @NotNull PlayerData playerData, @NotNull Consumable consumable, @NotNull NBTItem target, @Nullable Type targetType);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import net.Indyuce.mmoitems.stat.data.type.Mergeable;
|
||||
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
||||
import net.Indyuce.mmoitems.stat.data.type.UpgradeInfo;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -94,6 +95,12 @@ public class StatHistory {
|
||||
*/
|
||||
@NotNull public StatData getOriginalData() { return originalData; }
|
||||
|
||||
/**
|
||||
* The first value ever recorded of this stat, in this item.
|
||||
* Presumably from when it was first generated.
|
||||
*/
|
||||
public void setOriginalData(@NotNull StatData s) { originalData = s;}
|
||||
|
||||
/*
|
||||
* The final modifier being provided by each gemstone.
|
||||
* GemStones may have scaled with upgrades, that will be accounted for.
|
||||
@ -104,7 +111,10 @@ public class StatHistory {
|
||||
* The final modifier being provided by each gemstone.
|
||||
* GemStones may have scaled with upgrades, that will be accounted for.
|
||||
*/
|
||||
@Nullable public StatData getGemstoneData(UUID of) { return perGemstoneData.get(of); }
|
||||
@Contract("null -> null")
|
||||
@Nullable public StatData getGemstoneData(@Nullable UUID of) { if (of == null) { return null; } return perGemstoneData.get(of); }
|
||||
|
||||
public void removeGemData(@NotNull UUID of) { perGemstoneData.remove(of); }
|
||||
|
||||
/**
|
||||
* All the Stat Datas provided by GemStones
|
||||
@ -196,8 +206,8 @@ public class StatHistory {
|
||||
original = ofStat.getClearStatData();
|
||||
ofItem.setData(ofStat, original);
|
||||
//UPGRD//MMOItems.log("\u00a7e +\u00a77 Item didnt have this stat, original set as blanc.");
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
original = ((Mergeable) original).cloneData();
|
||||
//UPGRD//MMOItems.log("\u00a7a +\u00a77 Found original data");
|
||||
}
|
||||
@ -263,7 +273,7 @@ public class StatHistory {
|
||||
//UPGRD//MMOItems.log("\u00a76 ||\u00a77 Purged Stone: \u00a7e" + ext.toString());
|
||||
|
||||
// Remove
|
||||
perGemstoneData.remove(ext);
|
||||
removeGemData(ext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,108 +1,108 @@
|
||||
# Weapon Stats
|
||||
attack-damage: '&7➸ Attack Damage: &f#'
|
||||
attack-speed: '&7➸ Attack Speed: &f#'
|
||||
critical-strike-chance: '&7■ Crit Strike Chance: &f<plus>#%'
|
||||
critical-strike-power: '&7■ Crit Strike Power: &f<plus>#%'
|
||||
range: '&7■ Range: &f#'
|
||||
mana-cost: '&7■ Uses &9# Mana'
|
||||
stamina-cost: '&7■ Uses &9# Stamina'
|
||||
arrow-velocity: '&7■ Arrow Velocity: &f#'
|
||||
blunt-power: '&7■ Blunt Power: &f#'
|
||||
blunt-rating: '&7■ Blunt Rating: &f#%'
|
||||
two-handed: '&7■ Two Handed'
|
||||
handworn: '&7■ Handworn'
|
||||
knockback: '&7■ Knockback: &f#'
|
||||
recoil: '&7■ Recoil: &f#%'
|
||||
note-weight: '&7■ Note Weight: &f#'
|
||||
attack-damage: '&3 &7➸ Attack Damage: &f#'
|
||||
attack-speed: '&3 &7➸ Attack Speed: &f#'
|
||||
critical-strike-chance: '&3 &7■ Crit Strike Chance: &f<plus>#%'
|
||||
critical-strike-power: '&3 &7■ Crit Strike Power: &f<plus>#%'
|
||||
range: '&3 &7■ Range: &f#'
|
||||
mana-cost: '&3 &7■ Uses &9# Mana'
|
||||
stamina-cost: '&3 &7■ Uses &9# Stamina'
|
||||
arrow-velocity: '&3 &7■ Arrow Velocity: &f#'
|
||||
blunt-power: '&3 &7■ Blunt Power: &f#'
|
||||
blunt-rating: '&3 &7■ Blunt Rating: &f#%'
|
||||
two-handed: '&3 &7■ Two Handed'
|
||||
handworn: '&3 &7■ Handworn'
|
||||
knockback: '&3 &7■ Knockback: &f#'
|
||||
recoil: '&3 &7■ Recoil: &f#%'
|
||||
note-weight: '&3 &7■ Note Weight: &f#'
|
||||
|
||||
# Extra Damage
|
||||
pve-damage: '&7■ PvE Damage: &f<plus>#%'
|
||||
pvp-damage: '&7■ PvP Damage: &f<plus>#%'
|
||||
magic-damage: '&7■ Magic Damage: &f<plus>#%'
|
||||
weapon-damage: '&7■ Weapon Damage: &f<plus>#%'
|
||||
undead-damage: '&7■ Undead Damage: &f<plus>#%'
|
||||
skill-damage: '&7■ Skill Damage: &f<plus>#%'
|
||||
physical-damage: '&7■ Physical Damage: &f<plus>#%'
|
||||
projectile-damage: '&7■ Projectile Damage: &f<plus>#%'
|
||||
faction-damage-undead: '&7■ Undead Faction Damage: &f<plus>#%'
|
||||
pve-damage: '&3 &7■ PvE Damage: &f<plus>#%'
|
||||
pvp-damage: '&3 &7■ PvP Damage: &f<plus>#%'
|
||||
magic-damage: '&3 &7■ Magic Damage: &f<plus>#%'
|
||||
weapon-damage: '&3 &7■ Weapon Damage: &f<plus>#%'
|
||||
undead-damage: '&3 &7■ Undead Damage: &f<plus>#%'
|
||||
skill-damage: '&3 &7■ Skill Damage: &f<plus>#%'
|
||||
physical-damage: '&3 &7■ Physical Damage: &f<plus>#%'
|
||||
projectile-damage: '&3 &7■ Projectile Damage: &f<plus>#%'
|
||||
faction-damage-undead: '&3 &7■ Undead Faction Damage: &f<plus>#%'
|
||||
|
||||
# Abilities
|
||||
ability-format: '&a>&8| &7#c &8|&e|&8| &7&l#a'
|
||||
ability-format: '&a>&8| &7#c &8|&e|&8| &3 &7&l#a'
|
||||
ability-modifier: ' &3>&8|&7 #m&8: &f#v'
|
||||
ability-splitter: '&8'
|
||||
|
||||
# Armor Stats
|
||||
block-power: '&7■ Block Power: &f<plus>#%'
|
||||
block-rating: '&7■ Block Rating: &f<plus>#%'
|
||||
block-cooldown-reduction: '&7■ Block Cooldown Reduction: &f<plus>#%'
|
||||
dodge-rating: '&7■ Dodge Rating: &f<plus>#%'
|
||||
dodge-cooldown-reduction: '&7■ Dodge Cooldown Reduction: &f<plus>#%'
|
||||
parry-rating: '&7■ Parry Rating: &f<plus>#%'
|
||||
parry-cooldown-reduction: '&7■ Parry Cooldown Reduction: &f<plus>#%'
|
||||
armor: '&7✠ Armor: &f<plus>#'
|
||||
armor-toughness: '&7✠ Armor Toughness: &f<plus>#'
|
||||
knockback-resistance: '&7✠ Knockback Resistance: &f<plus>#%'
|
||||
max-health: '&7❤ Health:&c <plus>#'
|
||||
movement-speed: '&7■ Movement Speed: &f<plus>#'
|
||||
block-power: '&3 &7■ Block Power: &f<plus>#%'
|
||||
block-rating: '&3 &7■ Block Rating: &f<plus>#%'
|
||||
block-cooldown-reduction: '&3 &7■ Block Cooldown Reduction: &f<plus>#%'
|
||||
dodge-rating: '&3 &7■ Dodge Rating: &f<plus>#%'
|
||||
dodge-cooldown-reduction: '&3 &7■ Dodge Cooldown Reduction: &f<plus>#%'
|
||||
parry-rating: '&3 &7■ Parry Rating: &f<plus>#%'
|
||||
parry-cooldown-reduction: '&3 &7■ Parry Cooldown Reduction: &f<plus>#%'
|
||||
armor: '&3 &7✠ Armor: &f<plus>#'
|
||||
armor-toughness: '&3 &7✠ Armor Toughness: &f<plus>#'
|
||||
knockback-resistance: '&3 &7✠ Knockback Resistance: &f<plus>#%'
|
||||
max-health: '&3 &7❤ Health:&c <plus>#'
|
||||
movement-speed: '&3 &7■ Movement Speed: &f<plus>#'
|
||||
|
||||
# Damage Reduction
|
||||
defense: '&7■ Defense: &f<plus>#'
|
||||
damage-reduction: '&7■ Damage Reduction: &f<plus>#%'
|
||||
fall-damage-reduction: '&7■ Fall Damage Reduction: &f<plus>#%'
|
||||
fire-damage-reduction: '&7■ Fire Damage Reduction: &f<plus>#%'
|
||||
magic-damage-reduction: '&7■ Magic Damage Reduction: &f<plus>#%'
|
||||
projectile-damage-reduction: '&7■ Projectile Damage Reduction: &f<plus>#%'
|
||||
physical-damage-reduction: '&7■ Physical Damage Reduction: &f<plus>#%'
|
||||
defense: '&3 &7■ Defense: &f<plus>#'
|
||||
damage-reduction: '&3 &7■ Damage Reduction: &f<plus>#%'
|
||||
fall-damage-reduction: '&3 &7■ Fall Damage Reduction: &f<plus>#%'
|
||||
fire-damage-reduction: '&3 &7■ Fire Damage Reduction: &f<plus>#%'
|
||||
magic-damage-reduction: '&3 &7■ Magic Damage Reduction: &f<plus>#%'
|
||||
projectile-damage-reduction: '&3 &7■ Projectile Damage Reduction: &f<plus>#%'
|
||||
physical-damage-reduction: '&3 &7■ Physical Damage Reduction: &f<plus>#%'
|
||||
|
||||
# RPG stats
|
||||
health-regeneration: '&7■ Health Regeneration: &f<plus>#'
|
||||
max-mana: '&7■ Max Mana: &f<plus>#'
|
||||
mana-regeneration: '&7■ Mana Regeneration: &f<plus>#'
|
||||
max-stamina: '&7■ Max Stamina: &f<plus>#'
|
||||
stamina-regeneration: '&7■ Stamina Regeneration: &f<plus>#'
|
||||
cooldown-reduction: '&7■ Skill Cooldown Reduction: &f<plus>#%'
|
||||
additional-experience: '&7■ Additional Experience: &f<plus>#%'
|
||||
health-regeneration: '&3 &7■ Health Regeneration: &f<plus>#'
|
||||
max-mana: '&3 &7■ Max Mana: &f<plus>#'
|
||||
mana-regeneration: '&3 &7■ Mana Regeneration: &f<plus>#'
|
||||
max-stamina: '&3 &7■ Max Stamina: &f<plus>#'
|
||||
stamina-regeneration: '&3 &7■ Stamina Regeneration: &f<plus>#'
|
||||
cooldown-reduction: '&3 &7■ Skill Cooldown Reduction: &f<plus>#%'
|
||||
additional-experience: '&3 &7■ Additional Experience: &f<plus>#%'
|
||||
|
||||
# Extra Options
|
||||
perm-effect: '&7■ Permanent &f#'
|
||||
command: '&7■ Command: &f#c &7(&f#d&7s)'
|
||||
item-cooldown: '&7■ &f#&7s Cooldown'
|
||||
arrow-potion-effects: '&7■ Arrow Effect: &f#'
|
||||
perm-effect: '&3 &7■ Permanent &f#'
|
||||
command: '&3 &7■ Command: &f#c &3 &7(&f#d&3 &7s)'
|
||||
item-cooldown: '&3 &7■ &f#&3 &7s Cooldown'
|
||||
arrow-potion-effects: '&3 &7■ Arrow Effect: &f#'
|
||||
|
||||
# Consumables
|
||||
restore-health: '&7■ Restores &f# &7Health'
|
||||
restore-food: '&7■ Restores &f# &7Food'
|
||||
restore-saturation: '&7■ Restores &f# &7Saturation'
|
||||
restore-mana: '&7■ Restores &f# &7Mana'
|
||||
restore-stamina: '&7■ Restores &f# &7Stamina'
|
||||
effect: '&7■ Grants &f#e &7for &f#d&7s'
|
||||
repair: '&7■ Repair: &f#'
|
||||
can-identify: '&7■ Can identify items.'
|
||||
can-deconstruct: '&7■ Can deconstruct tiered items.'
|
||||
can-deskin: '&7■ Can de-skin skinned items.'
|
||||
success-rate: '&7■ Success Rate: &a&l#%'
|
||||
max-consume: '&7■ Max Consume: &f# &7uses'
|
||||
restore-health: '&3 &7■ Restores &f# &3 &7Health'
|
||||
restore-food: '&3 &7■ Restores &f# &3 &7Food'
|
||||
restore-saturation: '&3 &7■ Restores &f# &3 &7Saturation'
|
||||
restore-mana: '&3 &7■ Restores &f# &3 &7Mana'
|
||||
restore-stamina: '&3 &7■ Restores &f# &3 &7Stamina'
|
||||
effect: '&3 &7■ Grants &f#e &3 &7for &f#d&3 &7s'
|
||||
repair: '&3 &7■ Repair: &f#'
|
||||
can-identify: '&3 &7■ Can identify items.'
|
||||
can-deconstruct: '&3 &7■ Can deconstruct tiered items.'
|
||||
can-deskin: '&3 &7■ Can de-skin skinned items.'
|
||||
success-rate: '&3 &7■ Success Rate: &a&l#%'
|
||||
max-consume: '&3 &7■ Max Consume: &f# &3 &7uses'
|
||||
|
||||
# Gem Stones
|
||||
empty-gem-socket: '&a◆ Empty # Gem Socket'
|
||||
filled-gem-socket: '&a◆ #'
|
||||
when-applied: '&aWhen Applied:'
|
||||
gem-stone-lore: '&8&l[&2&l*&8&l] &aDrag onto an item &7to apply!'
|
||||
gem-stone-lore: '&8&l[&2&l*&8&l] &aDrag onto an item &3 &7to apply!'
|
||||
|
||||
# Soulbound
|
||||
soulbinding-chance: '&7■ Has a &a#%&7 chance to bind your item.'
|
||||
soulbound-break-chance: '&7■ Has a &a#%&7 chance to break soulbounds.'
|
||||
soulbound-level: '&7■ Level &e# &7Soulbound'
|
||||
soulbinding-chance: '&3 &7■ Has a &a#%&3 &7 chance to bind your item.'
|
||||
soulbound-break-chance: '&3 &7■ Has a &a#%&3 &7 chance to break soulbounds.'
|
||||
soulbound-level: '&3 &7■ Level &e# &3 &7Soulbound'
|
||||
|
||||
# Tool Enchants
|
||||
autosmelt: '&7■ &fAutosmelt'
|
||||
bouncing-crack: '&7■ &fBouncing Crack'
|
||||
pickaxe-power: '&7■ &fPickaxe Power: &a#'
|
||||
autosmelt: '&3 &7■ &fAutosmelt'
|
||||
bouncing-crack: '&3 &7■ &fBouncing Crack'
|
||||
pickaxe-power: '&3 &7■ &fPickaxe Power: &a#'
|
||||
|
||||
# General
|
||||
item-type: '&c#'
|
||||
tier: '&7Tier: #'
|
||||
required-class: '&7# Item'
|
||||
tier: '&3 &7Tier: #'
|
||||
required-class: '&3 &7# Item'
|
||||
required-level: '&eRequires Lvl #'
|
||||
# Attributes
|
||||
required-dexterity: '&eRequires &c# &eDexterity'
|
||||
@ -121,17 +121,17 @@ profession-woodcutting: '&eWoodcutting Level: &c#'
|
||||
|
||||
|
||||
# Elemental Damage
|
||||
fire-damage: '&c❖ #% Fire Damage'
|
||||
ice-damage: '&b❖ #% Ice Damage'
|
||||
earth-damage: '&2❖ #% Earth Damage'
|
||||
wind-damage: '&7❖ #% Wind Damage'
|
||||
thunder-damage: '&e❖ #% Thunder Damage'
|
||||
water-damage: '&3❖ #% Water Damage'
|
||||
fire-damage: '&c ❖ #% Fire Damage'
|
||||
ice-damage: '&b ❖ #% Ice Damage'
|
||||
earth-damage: '&2 ❖ #% Earth Damage'
|
||||
wind-damage: '&3 &7❖ #% Wind Damage'
|
||||
thunder-damage: '&e ❖ #% Thunder Damage'
|
||||
water-damage: '&3 ❖ #% Water Damage'
|
||||
|
||||
# Elemental Defense
|
||||
fire-defense: '&c❖ #% Fire Defense'
|
||||
ice-defense: '&b❖ #% Ice Defense'
|
||||
earth-defense: '&2❖ #% Earth Defense'
|
||||
wind-defense: '&7❖ #% Wind Defense'
|
||||
thunder-defense: '&e❖ #% Thunder Defense'
|
||||
water-defense: '&3❖ #% Water Defense'
|
||||
fire-defense: '&c ❖ #% Fire Defense'
|
||||
ice-defense: '&b ❖ #% Ice Defense'
|
||||
earth-defense: '&2 ❖ #% Earth Defense'
|
||||
wind-defense: '&3 &7❖ #% Wind Defense'
|
||||
thunder-defense: '&e ❖ #% Thunder Defense'
|
||||
water-defense: '&3 ❖ #% Water Defense'
|
||||
|
@ -1,107 +1,107 @@
|
||||
# Weapon Stats
|
||||
attack-damage: '&7➸ Daño de ataque: &f#'
|
||||
attack-speed: '&7➸ Velocidad de ataque: &f#'
|
||||
critical-strike-chance: '&7■ Probabilidad de crítico: &f<plus>#%'
|
||||
critical-strike-power: '&7■ Poder de crítico: &f<plus>#%'
|
||||
range: '&7■ Rango: &f#'
|
||||
attack-damage: '&3 &7➸ Daño de ataque: &f#'
|
||||
attack-speed: '&3 &7➸ Velocidad de ataque: &f#'
|
||||
critical-strike-chance: '&3 &7■ Probabilidad de crítico: &f<plus>#%'
|
||||
critical-strike-power: '&3 &7■ Poder de crítico: &f<plus>#%'
|
||||
range: '&3 &7■ Rango: &f#'
|
||||
mana-cost: '&9■ Usa # de Mana'
|
||||
stamina-cost: '&9■ Usa # de Stamina'
|
||||
arrow-velocity: '&7■ Velocidad de flechas: &f#'
|
||||
blunt-power: '&7■ Radio de Daño de Area: &f#'
|
||||
blunt-rating: '&7■ Fracción de Daño de Area: &f#%'
|
||||
two-handed: '&7■ Necesita ambas manos'
|
||||
handworn: '&7■ Ignora necesitar ambas manos'
|
||||
knockback: '&7■ Empuje: &f#'
|
||||
recoil: '&7■ Retroceso: &f#%'
|
||||
note-weight: '&7■ Peso Musical: &f#'
|
||||
arrow-velocity: '&3 &7■ Velocidad de flechas: &f#'
|
||||
blunt-power: '&3 &7■ Radio de Daño de Area: &f#'
|
||||
blunt-rating: '&3 &7■ Fracción de Daño de Area: &f#%'
|
||||
two-handed: '&3 &7■ Necesita ambas manos'
|
||||
handworn: '&3 &7■ Ignora necesitar ambas manos'
|
||||
knockback: '&3 &7■ Empuje: &f#'
|
||||
recoil: '&3 &7■ Retroceso: &f#%'
|
||||
note-weight: '&3 &7■ Peso Musical: &f#'
|
||||
|
||||
# Extra Damage
|
||||
pve-damage: '&7■ Daño PVE: &f<plus>#%'
|
||||
pvp-damage: '&7■ Daño PVP: &f<plus>#%'
|
||||
magic-damage: '&7■ Daño mágico: &f<plus>#%'
|
||||
weapon-damage: '&7■ Daño de arma: &f<plus>#%'
|
||||
undead-damage: '&7■ Daño a monstruos: &f<plus>#%'
|
||||
skill-damage: '&7■ Daño de abilidad: &f<plus>#%'
|
||||
physical-damage: '&7■ Daño físico: &f<plus>#%'
|
||||
projectile-damage: '&7■ Daño de projectiles: &f<plus>#%'
|
||||
faction-damage-undead: '&7■ Daño a los Undead: &f<plus>#%'
|
||||
pve-damage: '&3 &7■ Daño PVE: &f<plus>#%'
|
||||
pvp-damage: '&3 &7■ Daño PVP: &f<plus>#%'
|
||||
magic-damage: '&3 &7■ Daño mágico: &f<plus>#%'
|
||||
weapon-damage: '&3 &7■ Daño de arma: &f<plus>#%'
|
||||
undead-damage: '&3 &7■ Daño a monstruos: &f<plus>#%'
|
||||
skill-damage: '&3 &7■ Daño de abilidad: &f<plus>#%'
|
||||
physical-damage: '&3 &7■ Daño físico: &f<plus>#%'
|
||||
projectile-damage: '&3 &7■ Daño de projectiles: &f<plus>#%'
|
||||
faction-damage-undead: '&3 &7■ Daño a los Undead: &f<plus>#%'
|
||||
|
||||
# Abilities
|
||||
ability-format: '&a>&8| &7#c &8|&e|&8| &7&l#a'
|
||||
ability-format: '&a>&8| &7#c &8|&e|&8| &3 &7&l#a'
|
||||
ability-modifier: ' &3>&8|&7 #m&8: &f#v'
|
||||
ability-splitter: '&8'
|
||||
|
||||
# Armor Stats
|
||||
block-power: '&7■ Bloqueo: &f<plus>#%'
|
||||
block-rating: '&7■ Probabilidad de bloqueo: &f<plus>#%'
|
||||
block-cooldown-reduction: '&7■ Frequencia de bloqueo: &f<plus>#%'
|
||||
dodge-rating: '&7■ Probabilidad de evasión: &f<plus>#%'
|
||||
dodge-cooldown-reduction: '&7■ Frequencia de evasión: &f<plus>#%'
|
||||
parry-rating: '&7■ Probabilidad de contraatacar: &f<plus>#%'
|
||||
parry-cooldown-reduction: '&7■ Frequencia de contraataque: &f<plus>#%'
|
||||
armor: '&7✠ Defensa: &f<plus>#'
|
||||
armor-toughness: '&7✠ Resistencia de armadura: &f<plus>#'
|
||||
knockback-resistance: '&7✠ Resistencia al empuje: &f<plus>#%'
|
||||
block-power: '&3 &7■ Bloqueo: &f<plus>#%'
|
||||
block-rating: '&3 &7■ Probabilidad de bloqueo: &f<plus>#%'
|
||||
block-cooldown-reduction: '&3 &7■ Frequencia de bloqueo: &f<plus>#%'
|
||||
dodge-rating: '&3 &7■ Probabilidad de evasión: &f<plus>#%'
|
||||
dodge-cooldown-reduction: '&3 &7■ Frequencia de evasión: &f<plus>#%'
|
||||
parry-rating: '&3 &7■ Probabilidad de contraatacar: &f<plus>#%'
|
||||
parry-cooldown-reduction: '&3 &7■ Frequencia de contraataque: &f<plus>#%'
|
||||
armor: '&3 &7✠ Defensa: &f<plus>#'
|
||||
armor-toughness: '&3 &7✠ Resistencia de armadura: &f<plus>#'
|
||||
knockback-resistance: '&3 &7✠ Resistencia al empuje: &f<plus>#%'
|
||||
max-health: '&c❤ Vida máxima: <plus>#'
|
||||
movement-speed: '&7■ Velocidad: &f<plus>#'
|
||||
movement-speed: '&3 &7■ Velocidad: &f<plus>#'
|
||||
|
||||
# Damage Reduction
|
||||
defense: '&7■ Defensa: &f<plus>#'
|
||||
damage-reduction: '&7■ Reducción de daño: &f<plus>#%'
|
||||
fall-damage-reduction: '&7■ Reducción de daño por caída: &f<plus>#%'
|
||||
fire-damage-reduction: '&7■ Reducción de daño por fuego: &f<plus>#%'
|
||||
magic-damage-reduction: '&7■ Reducción de daño mágico: &f<plus>#%'
|
||||
projectile-damage-reduction: '&7■ Reducción de daño de projectiles: &f<plus>#%'
|
||||
physical-damage-reduction: '&7■ Reducción de daño físico: &f<plus>#%'
|
||||
defense: '&3 &7■ Defensa: &f<plus>#'
|
||||
damage-reduction: '&3 &7■ Reducción de daño: &f<plus>#%'
|
||||
fall-damage-reduction: '&3 &7■ Reducción de daño por caída: &f<plus>#%'
|
||||
fire-damage-reduction: '&3 &7■ Reducción de daño por fuego: &f<plus>#%'
|
||||
magic-damage-reduction: '&3 &7■ Reducción de daño mágico: &f<plus>#%'
|
||||
projectile-damage-reduction: '&3 &7■ Reducción de daño de projectiles: &f<plus>#%'
|
||||
physical-damage-reduction: '&3 &7■ Reducción de daño físico: &f<plus>#%'
|
||||
|
||||
# RPG Stats
|
||||
health-regeneration: '&7■ Regeneración de vida: &f<plus>#%'
|
||||
max-mana: '&7■ Mana máximo: &f<plus>#'
|
||||
mana-regeneration: '&7■ Regeneración de mana: &f<plus>#'
|
||||
max-stamina: '&7■ Stamina máxima: &f<plus>#'
|
||||
stamina-regeneration: '&7■ Regeneracion de stamina: &f<plus>#'
|
||||
cooldown-reduction: '&7■ Frequencia de abilidades: &f<plus>#%'
|
||||
additional-experience: '&7■ Experiencia adicional: &f<plus>#%'
|
||||
health-regeneration: '&3 &7■ Regeneración de vida: &f<plus>#%'
|
||||
max-mana: '&3 &7■ Mana máximo: &f<plus>#'
|
||||
mana-regeneration: '&3 &7■ Regeneración de mana: &f<plus>#'
|
||||
max-stamina: '&3 &7■ Stamina máxima: &f<plus>#'
|
||||
stamina-regeneration: '&3 &7■ Regeneracion de stamina: &f<plus>#'
|
||||
cooldown-reduction: '&3 &7■ Frequencia de abilidades: &f<plus>#%'
|
||||
additional-experience: '&3 &7■ Experiencia adicional: &f<plus>#%'
|
||||
|
||||
# Extra Options
|
||||
perm-effect: '&7■ Permanente &f#'
|
||||
command: '&7■ Comando: &f#c &7(&f#d&7s)'
|
||||
item-cooldown: '&7■ &7Se puede usar cada #&7s'
|
||||
arrow-potion-effects: '&7■ Flecha envinada: &f#'
|
||||
perm-effect: '&3 &7■ Permanente &f#'
|
||||
command: '&3 &7■ Comando: &f#c &3 &7(&f#d&3 &7s)'
|
||||
item-cooldown: '&3 &7■ &3 &7Se puede usar cada #&3 &7s'
|
||||
arrow-potion-effects: '&3 &7■ Flecha envinada: &f#'
|
||||
|
||||
# Consumables
|
||||
restore-health: '&7■ Da &f# &7de vida'
|
||||
restore-food: '&7■ Restaura &f# &7de hambre'
|
||||
restore-saturation: '&7■ Da &f# &7de saturación'
|
||||
restore-mana: '&7■ Da &f# &7de mana'
|
||||
restore-stamina: '&7■ Da &f# &7de stamina'
|
||||
effect: '&7■ Al consumir otorga &f#e &7por &f#d&7s'
|
||||
repair: '&7■ Repara: &f#'
|
||||
can-identify: '&7■ Puede identificar objetos.'
|
||||
can-deconstruct: '&7■ Puede destruir objetos usados.'
|
||||
success-rate: '&7■ Probabilidad de éxito: &a&l#%'
|
||||
max-consume: '&7■ Usos Restantes: &f#'
|
||||
restore-health: '&3 &7■ Da &f# &3 &7de vida'
|
||||
restore-food: '&3 &7■ Restaura &f# &3 &7de hambre'
|
||||
restore-saturation: '&3 &7■ Da &f# &3 &7de saturación'
|
||||
restore-mana: '&3 &7■ Da &f# &3 &7de mana'
|
||||
restore-stamina: '&3 &7■ Da &f# &3 &7de stamina'
|
||||
effect: '&3 &7■ Al consumir otorga &f#e &3 &7por &f#d&3 &7s'
|
||||
repair: '&3 &7■ Repara: &f#'
|
||||
can-identify: '&3 &7■ Puede identificar objetos.'
|
||||
can-deconstruct: '&3 &7■ Puede destruir objetos usados.'
|
||||
success-rate: '&3 &7■ Probabilidad de éxito: &a&l#%'
|
||||
max-consume: '&3 &7■ Usos Restantes: &f#'
|
||||
|
||||
# Gem Stones
|
||||
empty-gem-socket: '&a◆ Espacio para gema #'
|
||||
filled-gem-socket: '&a◆ #'
|
||||
when-applied: '&aAl aplicar:'
|
||||
gem-stone-lore: '&8&l[&2&l♦&8&l] &aArrastra y suelta en un objeto &7para aplicar!'
|
||||
gem-stone-lore: '&8&l[&2&l♦&8&l] &aArrastra y suelta en un objeto &3 &7para aplicar!'
|
||||
|
||||
# Soulbound
|
||||
soulbinding-chance: '&7■ Probabilidad de &a#%&7 de enlazarte astralmente.'
|
||||
soulbound-break-chance: '&7■ Probabilidad de &a#%&7 de romper enlazamientos astrales.'
|
||||
soulbound-level: '&7■ Nivel &e# &7de Enlazamiento Astral'
|
||||
soulbinding-chance: '&3 &7■ Probabilidad de &a#%&3 &7 de enlazarte astralmente.'
|
||||
soulbound-break-chance: '&3 &7■ Probabilidad de &a#%&3 &7 de romper enlazamientos astrales.'
|
||||
soulbound-level: '&3 &7■ Nivel &e# &3 &7de Enlazamiento Astral'
|
||||
|
||||
# Tool Enchants
|
||||
autosmelt: '&7■ &fAutofundidor'
|
||||
bouncing-crack: '&7■ &fGrieta Profunda'
|
||||
pickaxe-power: '&7■ &fPoder de Pico: &a#'
|
||||
autosmelt: '&3 &7■ &fAutofundidor'
|
||||
bouncing-crack: '&3 &7■ &fGrieta Profunda'
|
||||
pickaxe-power: '&3 &7■ &fPoder de Pico: &a#'
|
||||
|
||||
# General
|
||||
item-type: '&c#'
|
||||
tier: '&7Calidad: #'
|
||||
required-class: '&7Equipamento de #'
|
||||
tier: '&3 &7Calidad: #'
|
||||
required-class: '&3 &7Equipamento de #'
|
||||
required-level: '&eRequiere Nivel #'
|
||||
required-dexterity: '&eRequire &c# &ede Destreza'
|
||||
required-strength: '&eRequire &c# &ede Fuerza'
|
||||
@ -117,17 +117,17 @@ profession-smithing: '&eRequiere nivel de Herrero &c#'
|
||||
profession-woodcutting: '&eRequiere nivel de Leñador &c#'
|
||||
|
||||
# Elemental Damage
|
||||
fire-damage: '&c❖ #% Daño de fuego'
|
||||
ice-damage: '&b❖ #% Daño de hielo'
|
||||
earth-damage: '&2❖ #% Daño de tierra'
|
||||
wind-damage: '&7❖ #% Daño de viento'
|
||||
thunder-damage: '&e❖ #% Dañp de triemp'
|
||||
water-damage: '&3❖ #% Daño de agua'
|
||||
fire-damage: '&c ❖ #% Daño de fuego'
|
||||
ice-damage: '&b ❖ #% Daño de hielo'
|
||||
earth-damage: '&2 ❖ #% Daño de tierra'
|
||||
wind-damage: '&3 &7❖ #% Daño de viento'
|
||||
thunder-damage: '&e ❖ #% Dañp de triemp'
|
||||
water-damage: '&3 ❖ #% Daño de agua'
|
||||
|
||||
# Elemental Defense
|
||||
fire-defense: '&c❖ #% Defemsa al fuego'
|
||||
ice-defense: '&b❖ #% Defensa al hielo'
|
||||
earth-defense: '&2❖ #% Defensa de la tierra'
|
||||
wind-defense: '&7❖ #% Defensa al viento'
|
||||
thunder-defense: '&e❖ #% Defensa al trueno'
|
||||
water-defense: '&3❖ #% Defensa al agua'
|
||||
fire-defense: '&c ❖ #% Defemsa al fuego'
|
||||
ice-defense: '&b ❖ #% Defensa al hielo'
|
||||
earth-defense: '&2 ❖ #% Defensa de la tierra'
|
||||
wind-defense: '&3 &7❖ #% Defensa al viento'
|
||||
thunder-defense: '&e ❖ #% Defensa al trueno'
|
||||
water-defense: '&3 ❖ #% Defensa al agua'
|
||||
|
Loading…
Reference in New Issue
Block a user