Untargeted weapon durability changes

This commit is contained in:
Indyuce 2022-02-26 10:54:24 +01:00
parent cd5421b781
commit 8253113d33
10 changed files with 293 additions and 391 deletions

View File

@ -95,7 +95,7 @@ public class MMOItems extends LuminePlugin {
private VaultSupport vaultSupport;
private RPGHandler rpgPlugin;
private static final int MYTHICLIB_COMPATIBILITY_INDEX = 7;
private static final int MYTHICLIB_COMPATIBILITY_INDEX = 8;
public MMOItems() { plugin = this; }

View File

@ -13,7 +13,6 @@ import net.Indyuce.mmoitems.api.event.item.CustomDurabilityRepair;
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
import net.Indyuce.mmoitems.api.item.util.LoreUpdate;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.stat.data.DoubleData;
import net.Indyuce.mmoitems.stat.data.UpgradeData;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
@ -23,8 +22,8 @@ import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import java.util.Random;
/**
@ -39,10 +38,9 @@ import java.util.Random;
*/
public class DurabilityItem {
private final NBTItem nbtItem;
@Nullable
private final Player player;
private final int maxDurability, unbreakingLevel, initialDurability;
private final boolean barHidden;
private final Player player;
private int durability;
@ -55,7 +53,7 @@ public class DurabilityItem {
* @param player Player holding the item
* @param item Item with durability
*/
public DurabilityItem(@Nullable Player player, @NotNull ItemStack item) {
public DurabilityItem(@NotNull Player player, @NotNull ItemStack item) {
this(player, NBTItem.get(item));
}
@ -64,23 +62,21 @@ public class DurabilityItem {
* without using heavy MMOItem class methods
*
* @param player Player holding the item
* @param item Item with durability
* @param nbtItem Item with durability
*/
public DurabilityItem(@Nullable Player player, @NotNull NBTItem item) {
/*Validate.notNull(this.player = player, "Player cannot be null");*/
this.player = player;
Validate.notNull(nbtItem = item, "Item cannot be null");
public DurabilityItem(@NotNull Player player, @NotNull NBTItem nbtItem) {
this.player = Objects.requireNonNull(player, "Player cannot be null");
this.nbtItem = Objects.requireNonNull(nbtItem, "Item cannot be null");
maxDurability = nbtItem.getInteger("MMOITEMS_MAX_DURABILITY");
initialDurability = durability = nbtItem.hasTag("MMOITEMS_DURABILITY") ? nbtItem.getInteger("MMOITEMS_DURABILITY") : maxDurability;
barHidden = nbtItem.getBoolean("MMOITEMS_DURABILITY_BAR");
unbreakingLevel = (nbtItem.getItem().getItemMeta() != null && nbtItem.getItem().getItemMeta().hasEnchant(Enchantment.DURABILITY)) ?
nbtItem.getItem().getItemMeta().getEnchantLevel(Enchantment.DURABILITY) :
0;
nbtItem.getItem().getItemMeta().getEnchantLevel(Enchantment.DURABILITY) : 0;
}
@Nullable public Player getPlayer() {
public Player getPlayer() {
return player;
}
@ -92,19 +88,10 @@ public class DurabilityItem {
return durability;
}
// If the green vanilla durability bar should show
public boolean isBarHidden() {
return barHidden;
}
/**
* @deprecated Not used anymore
*/
@Deprecated
public boolean isUnbreakable() {
return nbtItem.getBoolean("Unbreakable");
}
public int getUnbreakingLevel() {
return unbreakingLevel;
}
@ -114,67 +101,23 @@ public class DurabilityItem {
}
public boolean isBroken() {
return nbtItem.hasTag("MMOITEMS_DURABILITY") && durability <= 0;
return durability <= 0;
}
public boolean isLostWhenBroken() {
return nbtItem.getBoolean("MMOITEMS_WILL_BREAK");
}
public boolean isDowngradedWhenBroken() {
return nbtItem.getBoolean("MMOITEMS_BREAK_DOWNGRADE");
}
/**
* <b>Assuming you already called {@link #isDowngradedWhenBroken()}</b>, when the item is
* being broken. This method will downgrade the item for one level and apply changes to
* the stored {@link #getNBTItem()}.
*
* If the item cannot be downgraded (due to not having upgrade data / reaching minimum
* upgrades), this method will return <code>null</code>, no change will be made to the
* NBTItem, and you should break the item.
*
* @return If the item could not be downgraded, and thus should break, will be <code>null</code>.
* If the item was successfully downgraded, this will uuuh, will return the NBTItem of
* the downgraded version.
*/
@Nullable public ItemStack shouldBreakWhenDowngraded() {
ItemTag uTag = ItemTag.getTagAtPath(ItemStats.UPGRADE.getNBTPath(), getNBTItem(), SupportedNBTTagValues.STRING);
if (uTag == null) { return null; }
try {
// Read data
UpgradeData data = new UpgradeData(new JsonParser().parse((String) uTag.getValue()).getAsJsonObject());
// If it cannot be downgraded (reached min), DEATH
if (data.getLevel() <= data.getMin()) { return null; }
// Downgrading operation
LiveMMOItem mmo = new LiveMMOItem(getNBTItem());
// Remove one level
mmo.getUpgradeTemplate().upgradeTo(mmo, data.getLevel() - 1);
// Build NBT
NBTItem preRet = mmo.newBuilder().buildNBT();
// Set durability to zero (full repair)
DurabilityItem dur = new DurabilityItem(getPlayer(), preRet);
dur.addDurability(dur.getMaxDurability());
// Yes
return dur.toItem();
} catch (JsonSyntaxException |IllegalStateException exception) { return null; }
}
/**
* Since
*
* @return If the item actually supports custom durability.
* @return If the item actually supports custom durability. It is completely
* disabled when the player is in creative mode just like vanilla durability.
*/
public boolean isValid() {
return maxDurability > 0 && player != null && player.getGameMode() != GameMode.CREATIVE;
return maxDurability > 0 && player.getGameMode() != GameMode.CREATIVE;
}
public DurabilityItem addDurability(int gain) {
@ -190,10 +133,7 @@ public class DurabilityItem {
}
public DurabilityItem decreaseDurability(int loss) {
CustomDurabilityDamage event = new CustomDurabilityDamage(this, loss);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled())
return this;
Validate.isTrue(loss > 0, "Loss must be greater than 0");
/*
* Calculate the chance of the item not losing any durability because of
@ -201,13 +141,18 @@ public class DurabilityItem {
* 1 chance out of (X + 1) to lose a durability point, that's 50% chance
* -> 33% chance -> 25% chance -> 20% chance...
*/
if (getUnbreakingLevel() > 0 && RANDOM.nextInt(getUnbreakingLevel()) > 0)
if (getUnbreakingLevel() > 0 && RANDOM.nextInt(getUnbreakingLevel()) != 0)
return this;
CustomDurabilityDamage event = new CustomDurabilityDamage(this, loss);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled())
return this;
durability = Math.max(0, Math.min(durability - loss, maxDurability));
// When the item breaks
if (durability <= 0 && player != null) {
// Play sound when item breaks
if (isBroken()) {
player.getWorld().playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, 1, 1);
PlayerData.get(player).getInventory().scheduleUpdate();
}
@ -215,12 +160,41 @@ public class DurabilityItem {
return this;
}
/**
* This method not only generates the newest item version taking into account
* 1) item damage
* 2) item breaking
* 3) item downgrade
*
* @return Newest version of the damaged item
*/
public ItemStack toItem() {
// No modification needs to be done
if (durability == initialDurability)
return nbtItem.getItem();
// Checks for possible downgrade
ItemTag uTag = ItemTag.getTagAtPath(ItemStats.UPGRADE.getNBTPath(), getNBTItem(), SupportedNBTTagValues.STRING);
if (uTag != null)
try {
UpgradeData data = new UpgradeData(new JsonParser().parse((String) uTag.getValue()).getAsJsonObject());
// If it cannot be downgraded (reached min), DEATH
if (data.getLevel() <= data.getMin())
return null;
// Remove one level and FULLY repair item
LiveMMOItem mmo = new LiveMMOItem(getNBTItem());
mmo.getUpgradeTemplate().upgradeTo(mmo, data.getLevel() - 1);
NBTItem preRet = mmo.newBuilder().buildNBT();
preRet.addTag(new ItemTag("MMOITEMS_DURABILITY", maxDurability));
return preRet.toItem();
} catch (JsonSyntaxException | IllegalStateException ignored) {
// Nothing
}
/*
* Cross multiplication to display the current item durability on the
* item durability bar. (1 - ratio) because minecraft works with item
@ -232,9 +206,9 @@ public class DurabilityItem {
* enchant.
*/
if (!barHidden) {
int damage = (durability == maxDurability) ? 0
: Math.max(1, (int) ((1. - ((double) durability / maxDurability)) * nbtItem.getItem().getType().getMaxDurability()));
nbtItem.addTag(new ItemTag("Damage", damage)); }
int damage = (durability == maxDurability) ? 0 : Math.max(1, (int) ((1. - ((double) durability / maxDurability)) * nbtItem.getItem().getType().getMaxDurability()));
nbtItem.addTag(new ItemTag("Damage", damage));
}
nbtItem.addTag(new ItemTag("MMOITEMS_DURABILITY", durability));

View File

@ -1,24 +1,16 @@
package net.Indyuce.mmoitems.api.interaction.util;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.SupportedNBTTagValues;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.stat.data.UpgradeData;
import org.bukkit.entity.Player;
import io.lumine.mythic.lib.api.item.NBTItem;
import org.bukkit.inventory.ItemStack;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import org.bukkit.entity.Player;
public class UntargetedDurabilityItem extends DurabilityItem {
private final EquipmentSlot slot;
/*
* Allows to handle custom durability for target weapons when they are
* left/right click while using the same durability system for both weapon
* types
/**
* Allows to handle custom durability for target weapons when
* they are left/right clicked while using the same durability
* system for both weapon types
*/
public UntargetedDurabilityItem(Player player, NBTItem item, EquipmentSlot slot) {
super(player, item);
@ -31,41 +23,15 @@ public class UntargetedDurabilityItem extends DurabilityItem {
return (UntargetedDurabilityItem) super.decreaseDurability(loss);
}
public void update() {
public void inventoryUpdate() {
// Cannot update null player
if (getPlayer() == null) { return; }
// If it broke (funny)
if (isBroken()) {
// Attempt to counter by downgrading
if (isDowngradedWhenBroken()) {
ItemStack counterUpgraded = shouldBreakWhenDowngraded();
if (counterUpgraded != null) {
// Edit item
getNBTItem().getItem().setItemMeta(counterUpgraded.getItemMeta());
// No more
return;
}
}
// Still here? Remove if lost when broken
if (isLostWhenBroken()) {
// Delete item
if (slot == EquipmentSlot.OFF_HAND) {
if (isBroken() && isLostWhenBroken()) {
if (slot == EquipmentSlot.OFF_HAND)
getPlayer().getInventory().setItemInOffHand(null);
} else { getPlayer().getInventory().setItemInMainHand(null); }
// No more
else
getPlayer().getInventory().setItemInMainHand(null);
return;
}
}
getNBTItem().getItem().setItemMeta(toItem().getItemMeta());
}

View File

@ -26,17 +26,17 @@ public class Crossbow extends UntargetedWeapon {
if (getPlayer().getGameMode() != GameMode.CREATIVE && !getPlayer().getInventory().containsAtLeast(new ItemStack(Material.ARROW), 1))
return;
UntargetedDurabilityItem durItem = new UntargetedDurabilityItem(getPlayer(), getNBTItem(), slot);
if (durItem.isBroken())
return;
PlayerMetadata stats = getPlayerData().getStats().newTemporary(slot);
if (!applyWeaponCosts(1 / getValue(stats.getStat("ATTACK_SPEED"), MMOItems.plugin.getConfig().getDouble("default.attack-speed")),
CooldownType.ATTACK))
return;
UntargetedDurabilityItem durItem = new UntargetedDurabilityItem(getPlayer(), getNBTItem(), slot);
if (durItem.isBroken())
return;
if (durItem.isValid())
durItem.decreaseDurability(1).update();
durItem.decreaseDurability(1).inventoryUpdate();
// consume arrow
// has to be after the CD check

View File

@ -35,17 +35,18 @@ public class Lute extends UntargetedWeapon {
@Override
public void untargetedAttack(EquipmentSlot slot) {
PlayerMetadata stats = getPlayerData().getStats().newTemporary(slot);
double attackSpeed = 1 / getValue(stats.getStat("ATTACK_SPEED"), MMOItems.plugin.getConfig().getDouble("default.attack-speed"));
if (!applyWeaponCosts(attackSpeed, CooldownType.ATTACK))
return;
UntargetedDurabilityItem durItem = new UntargetedDurabilityItem(getPlayer(), getNBTItem(), slot);
if (durItem.isBroken())
return;
PlayerMetadata stats = getPlayerData().getStats().newTemporary(slot);
double attackSpeed = 1 / getValue(stats.getStat("ATTACK_SPEED"), MMOItems.plugin.getConfig().getDouble("default.attack-speed"));
if (!applyWeaponCosts(attackSpeed, CooldownType.ATTACK))
return;
if (durItem.isValid())
durItem.decreaseDurability(1).update();
durItem.decreaseDurability(1).inventoryUpdate();
double attackDamage = getValue(stats.getStat("ATTACK_DAMAGE"), 7);
double range = getValue(getNBTItem().getStat(ItemStats.RANGE.getId()), MMOItems.plugin.getConfig().getDouble("default.range"));

View File

@ -28,18 +28,18 @@ public class Musket extends UntargetedWeapon {
@Override
public void untargetedAttack(EquipmentSlot slot) {
PlayerMetadata stats = getPlayerData().getStats().newTemporary(slot);
if (!applyWeaponCosts(1 / getValue(stats.getStat("ATTACK_SPEED"), MMOItems.plugin.getConfig().getDouble("default.attack-speed")),
CooldownType.ATTACK))
return;
UntargetedDurabilityItem durItem = new UntargetedDurabilityItem(getPlayer(), getNBTItem(), slot);
if (durItem.isBroken())
return;
PlayerMetadata stats = getPlayerData().getStats().newTemporary(slot);
if (!applyWeaponCosts(1 / getValue(stats.getStat("ATTACK_SPEED"), MMOItems.plugin.getConfig().getDouble("default.attack-speed")),
CooldownType.ATTACK))
return;
if (durItem.isValid())
durItem.decreaseDurability(1).update();
durItem.decreaseDurability(1).inventoryUpdate();
double attackDamage = stats.getStat("ATTACK_DAMAGE");
double range = getValue(getNBTItem().getStat(ItemStats.RANGE.getId()), MMOItems.plugin.getConfig().getDouble("default.range"));

View File

@ -32,17 +32,17 @@ public class Staff extends UntargetedWeapon {
@Override
public void untargetedAttack(EquipmentSlot slot) {
UntargetedDurabilityItem durItem = new UntargetedDurabilityItem(getPlayer(), getNBTItem(), slot);
if (durItem.isBroken())
return;
PlayerMetadata stats = getPlayerData().getStats().newTemporary(slot);
if (!applyWeaponCosts(1 / getValue(stats.getStat("ATTACK_SPEED"), MMOItems.plugin.getConfig().getDouble("default.attack-speed")),
CooldownType.ATTACK))
return;
UntargetedDurabilityItem durItem = new UntargetedDurabilityItem(getPlayer(), getNBTItem(), slot);
if (durItem.isBroken())
return;
if (durItem.isValid())
durItem.decreaseDurability(1).update();
durItem.decreaseDurability(1).inventoryUpdate();
double attackDamage = getValue(stats.getStat("ATTACK_DAMAGE"), 1);
double range = getValue(getNBTItem().getStat(ItemStats.RANGE.getId()), MMOItems.plugin.getConfig().getDouble("default.range"));

View File

@ -29,17 +29,17 @@ public class Whip extends UntargetedWeapon {
@Override
public void untargetedAttack(EquipmentSlot slot) {
UntargetedDurabilityItem durItem = new UntargetedDurabilityItem(getPlayer(), getNBTItem(), slot);
if (durItem.isBroken())
return;
PlayerMetadata stats = getPlayerData().getStats().newTemporary(slot);
if (!applyWeaponCosts(1 / getValue(stats.getStat("ATTACK_SPEED"), MMOItems.plugin.getConfig().getDouble("default.attack-speed")),
CooldownType.ATTACK))
return;
UntargetedDurabilityItem durItem = new UntargetedDurabilityItem(getPlayer(), getNBTItem(), slot);
if (durItem.isBroken())
return;
if (durItem.isValid())
durItem.decreaseDurability(1).update();
durItem.decreaseDurability(1).inventoryUpdate();
double attackDamage = getValue(stats.getStat("ATTACK_DAMAGE"), 7);
double range = getValue(getNBTItem().getStat(ItemStats.RANGE.getId()), MMOItems.plugin.getConfig().getDouble("default.range"));

View File

@ -1,9 +1,8 @@
package net.Indyuce.mmoitems.api.item.mmoitem;
import io.lumine.mythic.lib.api.item.NBTItem;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.api.Type;
import io.lumine.mythic.lib.api.item.NBTItem;
import net.Indyuce.mmoitems.api.interaction.util.DurabilityItem;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
@ -29,19 +28,11 @@ public abstract class ReadMMOItem extends MMOItem {
public int getDamage() {
// Does it use custom durability?
if (hasData(ItemStats.MAX_DURABILITY)) {
// Use the correct class
DurabilityItem dItem = new DurabilityItem(null, getNBT());
int max = dItem.getMaxDurability();
int current = dItem.getDurability();
// Difference
return max - current;
if (hasData(ItemStats.MAX_DURABILITY))
return getNBT().hasTag("MMOITEMS_DURABILITY") ? getNBT().getInteger("MMOITEMS_MAX_DURABILITY") - getNBT().getInteger("MMOITEMS_DURABILITY") : 0;
// Its using vanilla durability-yo
} else {
else {
// Uh use the item stack I guess
ItemStack asStack = getNBT().getItem();

View File

@ -25,7 +25,7 @@ public class DurabilityListener implements Listener {
private final List<DamageCause> ignoredCauses = Arrays.asList(DamageCause.DROWNING, DamageCause.SUICIDE, DamageCause.FALL, DamageCause.VOID,
DamageCause.FIRE_TICK, DamageCause.SUFFOCATION, DamageCause.POISON, DamageCause.WITHER, DamageCause.STARVATION, DamageCause.MAGIC);
private final EquipmentSlot[] armorSlots = { EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET };
private final EquipmentSlot[] armorSlots = {EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET};
/**
* Handles custom durability for non-'vanilla durability' items
@ -66,7 +66,6 @@ public class DurabilityListener implements Listener {
@EventHandler(ignoreCancelled = true)
public void itemDamage(PlayerItemDamageEvent event) {
DurabilityItem item = new DurabilityItem(event.getPlayer(), event.getItem());
if (item.isValid()) {
// Calculate item durability loss
@ -78,21 +77,6 @@ public class DurabilityListener implements Listener {
*/
if (item.isBroken()) {
// Attempt to counter by downgrading
if (item.isDowngradedWhenBroken()) {
ItemStack counterUpgraded = item.shouldBreakWhenDowngraded();
if (counterUpgraded != null) {
// Counter Event
event.setCancelled(true);
event.getItem().setItemMeta(counterUpgraded.getItemMeta());
// No more
return;
}
}
// Still here? Remove if lost when broken
if (item.isLostWhenBroken()) {
@ -130,20 +114,6 @@ public class DurabilityListener implements Listener {
if (item.isBroken()) {
// Attempt to counter by downgrading
if (item.isDowngradedWhenBroken()) {
ItemStack counterUpgraded = item.shouldBreakWhenDowngraded();
if (counterUpgraded != null) {
// Edit item
player.getInventory().getItem(slot).setItemMeta(counterUpgraded.getItemMeta());
// No more
return;
}
}
// Still here? Remove if lost when broken
if (item.isLostWhenBroken()) {