mirror of
https://gitlab.com/phoenix-dvpmt/mmoitems.git
synced 2025-02-22 14:41:48 +01:00
Fixed an issue with stat application
This commit is contained in:
parent
9689bfb7b0
commit
6d94bee39b
@ -1,39 +1,19 @@
|
||||
package net.Indyuce.mmoitems.api.interaction.projectile;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.gson.JsonParser;
|
||||
import io.lumine.mythic.lib.player.particle.ParticleInformation;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
/**
|
||||
* @deprecated Merge with {@link ParticleInformation}
|
||||
*/
|
||||
@Deprecated
|
||||
public class ArrowParticles extends BukkitRunnable {
|
||||
private final Arrow arrow;
|
||||
|
||||
private final Particle particle;
|
||||
private final int amount;
|
||||
private final float offset, speed;
|
||||
private final Color color;
|
||||
private final ParticleInformation particleInfo;
|
||||
|
||||
public ArrowParticles(Arrow arrow, NBTItem item) {
|
||||
this.arrow = arrow;
|
||||
|
||||
JsonObject object = new JsonParser().parse(item.getString("MMOITEMS_ARROW_PARTICLES")).getAsJsonObject();
|
||||
particle = Particle.valueOf(object.get("Particle").getAsString());
|
||||
amount = object.get("Amount").getAsInt();
|
||||
offset = (float) object.get("Offset").getAsDouble();
|
||||
|
||||
boolean colored = object.get("Colored").getAsBoolean();
|
||||
color = colored ? Color.fromRGB(object.get("Red").getAsInt(), object.get("Green").getAsInt(), object.get("Blue").getAsInt()) : null;
|
||||
speed = colored ? 0 : object.get("Speed").getAsFloat();
|
||||
this.particleInfo = new ParticleInformation(JsonParser.parseString(item.getString("MMOITEMS_ARROW_PARTICLES")).getAsJsonObject());
|
||||
|
||||
runTaskTimer(MMOItems.plugin, 0, 1);
|
||||
}
|
||||
@ -45,20 +25,6 @@ public class ArrowParticles extends BukkitRunnable {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO Allow Note to be colored and allow BLOCK_DUST/ITEM_DUST to pick a block/item.
|
||||
if (color != null) {
|
||||
if (particle == Particle.REDSTONE) {
|
||||
arrow.getWorld().spawnParticle(particle, arrow.getLocation().add(0, .25, 0), amount, offset, offset, offset, new Particle.DustOptions(color, 1));
|
||||
} else if (particle == Particle.SPELL_MOB || particle == Particle.SPELL_MOB_AMBIENT) {
|
||||
// 0 for amount to allow colors (Thats why there is a for loop). Then the offsets are RGB values from 0.0 - 1.0, last 1 is the brightness.
|
||||
for (int i = 0; i < amount; i++) {
|
||||
arrow.getWorld().spawnParticle(particle, arrow.getLocation().add(0, .25, 0), 0, (float) color.getRed() / 255, (float) color.getGreen() / 255, (float) color.getBlue() / 255, 1);
|
||||
}
|
||||
}
|
||||
// else if (particle == Particle.NOTE) { Do Fancy Color Stuff Good Luck }
|
||||
// The above code semi-worked for note particles but I think there is a limited amount of colors so its harder and prob have to get the nearest one.
|
||||
} else {
|
||||
arrow.getWorld().spawnParticle(particle, arrow.getLocation().add(0, .25, 0), amount, offset, offset, offset, speed);
|
||||
}
|
||||
particleInfo.display(arrow.getLocation().add(0, .25, 0));
|
||||
}
|
||||
}
|
||||
|
@ -6,23 +6,31 @@ import com.google.gson.JsonObject;
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.player.PlayerMetadata;
|
||||
import net.Indyuce.mmoitems.manager.EntityManager;
|
||||
import net.Indyuce.mmoitems.stat.data.PotionEffectData;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
/**
|
||||
* Since MMOItems 6.7.5 vanilla bows and custom bows are
|
||||
* not treated the same way:
|
||||
* - vanilla bows see NO changes in their damage computations
|
||||
* - custom bows override
|
||||
*/
|
||||
public class ProjectileData {
|
||||
private final NBTItem sourceItem;
|
||||
private final PlayerMetadata shooter;
|
||||
private final boolean customWeapon;
|
||||
private final double damageMultiplier;
|
||||
|
||||
private double cachedInitialDamage;
|
||||
@Deprecated
|
||||
public ProjectileData(PlayerMetadata shooter, NBTItem sourceItem, boolean customWeapon, double damageMultiplier) {
|
||||
this(shooter, sourceItem, damageMultiplier);
|
||||
}
|
||||
|
||||
public ProjectileData(PlayerMetadata shooter, NBTItem sourceItem, boolean customWeapon) {
|
||||
public ProjectileData(PlayerMetadata shooter, NBTItem sourceItem, double damageMultiplier) {
|
||||
this.shooter = shooter;
|
||||
this.sourceItem = sourceItem;
|
||||
this.customWeapon = customWeapon;
|
||||
this.damageMultiplier = damageMultiplier;
|
||||
}
|
||||
|
||||
public NBTItem getSourceItem() {
|
||||
@ -33,6 +41,10 @@ public class ProjectileData {
|
||||
return shooter;
|
||||
}
|
||||
|
||||
public double getDamageMultiplier() {
|
||||
return damageMultiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check if that projectile data is linked to
|
||||
* a projectile that want sent using a MMOItems bow.
|
||||
@ -40,46 +52,30 @@ public class ProjectileData {
|
||||
* If so, it needs to apply on-hit effects like
|
||||
* elemental damage or on-hit potion effects
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isCustomWeapon() {
|
||||
return customWeapon;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attack damage is handled in a weird fashion for projectile
|
||||
* attacks. Attack damage is not stored in a simple field but
|
||||
* rather the player's attack damage stat is temporarily changed.
|
||||
* <p>
|
||||
* Using this convention the attack damage is handled the same
|
||||
* way for both melee and projectile attacks.
|
||||
* Will throw an error if it's not a custom bow
|
||||
*
|
||||
* @return Projectile damage, not taking into account crits and
|
||||
* on-hit effects which are only applied afterwards by MythicLib
|
||||
* @return Damage of custom bow
|
||||
*/
|
||||
public double getDamage() {
|
||||
Validate.isTrue(isCustomWeapon(), "Not a custom bow");
|
||||
return shooter.getStat("ATTACK_DAMAGE");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see {@link #getDamage()}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setDamage(double damage) {
|
||||
Validate.isTrue(isCustomWeapon(), "Not a custom bow");
|
||||
shooter.setStat("ATTACK_DAMAGE", damage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see {@link EntityManager#cacheInitialProjectileDamage(EntityDamageByEntityEvent)}
|
||||
*/
|
||||
public double getCachedInitialDamage() {
|
||||
return cachedInitialDamage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see {@link EntityManager#cacheInitialProjectileDamage(EntityDamageByEntityEvent)}
|
||||
*/
|
||||
public void cacheInitialDamage(double cachedInitialDamage) {
|
||||
this.cachedInitialDamage = cachedInitialDamage;
|
||||
}
|
||||
|
||||
public void applyPotionEffects(LivingEntity target) {
|
||||
if (sourceItem.hasTag("MMOITEMS_ARROW_POTION_EFFECTS"))
|
||||
for (JsonElement entry : MythicLib.plugin.getJson().parse(sourceItem.getString("MMOITEMS_ARROW_POTION_EFFECTS"), JsonArray.class)) {
|
||||
|
@ -37,7 +37,7 @@ public class Crossbow extends UntargetedWeapon {
|
||||
getPlayer().getWorld().playSound(getPlayer().getLocation(), Sound.ENTITY_ARROW_SHOOT, 1, 1);
|
||||
|
||||
// Register custom projectile
|
||||
MMOItems.plugin.getEntities().registerCustomProjectile(getNBTItem(), stats, arrow, true, 1);
|
||||
MMOItems.plugin.getEntities().registerCustomProjectile(getNBTItem(), stats, arrow, 1);
|
||||
|
||||
// Trigger abilities
|
||||
stats.getData().triggerSkills(TriggerType.SHOOT_BOW, arrow);
|
||||
|
@ -75,7 +75,7 @@ public class PlayerStats {
|
||||
ModifierSource source = type == null ? ModifierSource.OTHER : type.getItemSet().getModifierSource();
|
||||
|
||||
// Apply hand weapon stat offset
|
||||
if (item.getSlot().isHand() && stat instanceof AttackWeaponStat)
|
||||
if (item.getSlot() == EquipmentSlot.MAIN_HAND && stat instanceof AttackWeaponStat)
|
||||
value -= ((AttackWeaponStat) stat).getOffset(playerData);
|
||||
|
||||
packet.addModifier(new StatModifier("MMOItem-" + index++, stat.getId(), value, ModifierType.FLAT, item.getSlot(), source));
|
||||
|
@ -69,15 +69,13 @@ public class EquippedItem {
|
||||
if (type == null)
|
||||
return false;
|
||||
|
||||
// Equips anywhere
|
||||
if (slot == EquipmentSlot.ANY)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Main hand items apply their stats and options in off
|
||||
* hand as well but the reciprocal is false
|
||||
*/
|
||||
if (type.getEquipmentType() == EquipmentSlot.MAIN_HAND)
|
||||
return slot.isHand();
|
||||
// Does it work in offhand
|
||||
if (slot == EquipmentSlot.OFF_HAND)
|
||||
return type.isOffhandItem();
|
||||
|
||||
return slot == type.getEquipmentType();
|
||||
}
|
||||
|
@ -274,10 +274,10 @@ public class ItemUse implements Listener {
|
||||
if (!(event.getProjectile() instanceof Arrow) || !(event.getEntity() instanceof Player))
|
||||
return;
|
||||
|
||||
NBTItem item = NBTItem.get(event.getBow());
|
||||
Type type = Type.get(item.getType());
|
||||
final NBTItem item = NBTItem.get(event.getBow());
|
||||
final Type type = Type.get(item.getType());
|
||||
final PlayerData playerData = PlayerData.get((Player) event.getEntity());
|
||||
|
||||
PlayerData playerData = PlayerData.get((Player) event.getEntity());
|
||||
if (type != null) {
|
||||
Weapon weapon = new Weapon(playerData, item);
|
||||
if (!weapon.checkItemRequirements() || !weapon.checkAndApplyWeaponCosts()) {
|
||||
@ -285,20 +285,15 @@ public class ItemUse implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
/*if (!checkDualWield((Player) event.getEntity(), item, bowSlot)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
|
||||
// Have to get hand manually because 1.15 and below does not have event.getHand()
|
||||
ItemStack itemInMainHand = playerData.getPlayer().getInventory().getItemInMainHand();
|
||||
EquipmentSlot bowSlot = itemInMainHand.isSimilar(event.getBow()) ? EquipmentSlot.MAIN_HAND : EquipmentSlot.OFF_HAND;
|
||||
final EquipmentSlot bowSlot = itemInMainHand.isSimilar(event.getBow()) ? EquipmentSlot.MAIN_HAND : EquipmentSlot.OFF_HAND;
|
||||
MMOItems.plugin.getEntities().registerCustomProjectile(item, playerData.getStats().newTemporary(bowSlot), event.getProjectile(), event.getForce());
|
||||
}
|
||||
|
||||
Arrow arrow = (Arrow) event.getProjectile();
|
||||
final Arrow arrow = (Arrow) event.getProjectile();
|
||||
if (item.getStat("ARROW_VELOCITY") > 0)
|
||||
arrow.setVelocity(arrow.getVelocity().multiply(item.getStat("ARROW_VELOCITY")));
|
||||
MMOItems.plugin.getEntities().registerCustomProjectile(item, playerData.getStats().newTemporary(bowSlot), event.getProjectile(), type != null, event.getForce());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,8 @@
|
||||
package net.Indyuce.mmoitems.manager;
|
||||
|
||||
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.damage.ProjectileAttackMetadata;
|
||||
import io.lumine.mythic.lib.player.PlayerMetadata;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.interaction.projectile.ArrowParticles;
|
||||
@ -8,7 +10,10 @@ import net.Indyuce.mmoitems.api.interaction.projectile.EntityData;
|
||||
import net.Indyuce.mmoitems.api.interaction.projectile.ProjectileData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
@ -33,33 +38,24 @@ public class EntityManager implements Listener {
|
||||
|
||||
private final Map<Integer, ProjectileData> projectiles = new WeakHashMap<>();
|
||||
|
||||
@Deprecated
|
||||
public void registerCustomProjectile(@NotNull NBTItem sourceItem, @NotNull PlayerMetadata attacker, @NotNull Entity entity, boolean customWeapon, double damageMultiplicator) {
|
||||
registerCustomProjectile(sourceItem, attacker, entity, damageMultiplicator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a custom projectile. This is used for bows, crossbows and tridents.
|
||||
* <p>
|
||||
* Default bow/trident damage is set to 7 just like vanilla Minecraft.
|
||||
*
|
||||
* @param sourceItem Item used to shoot the projectile
|
||||
* @param attacker Cached stats of the player shooting the projectile
|
||||
* @param entity The custom entity
|
||||
* @param customWeapon Is the source weapon is a custom item
|
||||
* @param damageMultiplicator The damage coefficient. For bows, this is basically the pull force.
|
||||
* For tridents or anything else this is always set to 1
|
||||
*/
|
||||
public void registerCustomProjectile(@NotNull NBTItem sourceItem, @NotNull PlayerMetadata attacker, @NotNull Entity entity, boolean customWeapon, double damageMultiplicator) {
|
||||
public void registerCustomProjectile(@NotNull NBTItem sourceItem, @NotNull PlayerMetadata attacker, @NotNull Entity entity, double damageMultiplicator) {
|
||||
|
||||
// Initialize projectile data
|
||||
ProjectileData projectileData = new ProjectileData(attacker, sourceItem, customWeapon);
|
||||
|
||||
/*
|
||||
* For bows, MC default value is 7. When using custom bows, the attack
|
||||
* damage stats returns the correct amount of damage. When using a vanilla
|
||||
* bow, attack damage is set to 2 because it's the default fist damage value.
|
||||
* Therefore MMOItems adds 5 to match the vanilla bow damage which is 7.
|
||||
*
|
||||
* Damage coefficient is how much you pull the bow. It's a float between
|
||||
* 0 and 1 for bows, and it is always 1 for tridents or crossbows.
|
||||
*/
|
||||
projectileData.setDamage((attacker.getStat("ATTACK_DAMAGE") + (customWeapon ? 0 : 5)) * damageMultiplicator);
|
||||
final ProjectileData projectileData = new ProjectileData(attacker, sourceItem, damageMultiplicator);
|
||||
|
||||
/*
|
||||
* Load arrow particles if the entity is an arrow and if the item has
|
||||
@ -100,84 +96,54 @@ public class EntityManager implements Listener {
|
||||
entities.remove(entity.getEntityId());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void unregisterEntityData(EntityDeathEvent event) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, () -> unregisterCustomEntity(event.getEntity()));
|
||||
}
|
||||
|
||||
/**
|
||||
* This fixes an issue with Heroes and MythicMobs as they are
|
||||
* plugins which MODIFY or apply damage modifiers to bow hit events.
|
||||
* This event is called on LOWEST and only edits the custom bow base damage.
|
||||
* It does NOT take into account the base damage passed in Bow#getDamage()
|
||||
* and fully overrides any change.
|
||||
* <p>
|
||||
* By caching the event damage with LOWEST priority you basically store
|
||||
* the VANILLA amount of damage the bow would have dealt if there was no
|
||||
* plugin.
|
||||
* <p>
|
||||
* The main problem comes from not being able to SET the bow damage. You are
|
||||
* only allowed to add flat modifiers to it, and if all the plugins do that
|
||||
* the calculations are fully correct.
|
||||
* <p>
|
||||
* On NORMAL priority, MMOItems calculates the bow damage, substract from that
|
||||
* the vanilla bow damage which outputs the damage modifier from MMOItems. This
|
||||
* makes it compatible with other plugins modifying the damage.
|
||||
*
|
||||
* @see {@link #applyOnHitEffects(EntityDamageByEntityEvent)}
|
||||
* Event order: ProjectileHit -> EntityDamage / EntityDeathEvent
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void cacheInitialProjectileDamage(EntityDamageByEntityEvent event) {
|
||||
if (event.getEntity() instanceof Projectile) {
|
||||
|
||||
/*
|
||||
* Some projectiles like Shulker Missiles are not handled
|
||||
* by MMOItems, therefore it needs to check if it's in the
|
||||
* projectile data map first before doing anything
|
||||
*/
|
||||
ProjectileData projData = projectiles.get(event.getEntity().getEntityId());
|
||||
if (projData != null)
|
||||
projData.cacheInitialDamage(event.getDamage());
|
||||
}
|
||||
}
|
||||
|
||||
// Projectile damage and effects
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void applyOnHitEffects(EntityDamageByEntityEvent event) {
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void customBowDamage(EntityDamageByEntityEvent event) {
|
||||
if (!(event.getDamager() instanceof Projectile) || !(event.getEntity() instanceof LivingEntity) || event.getEntity().hasMetadata("NPC"))
|
||||
return;
|
||||
|
||||
Projectile projectile = (Projectile) event.getDamager();
|
||||
ProjectileData data = projectiles.get(projectile.getEntityId());
|
||||
final Projectile projectile = (Projectile) event.getDamager();
|
||||
final ProjectileData data = projectiles.get(projectile.getEntityId());
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
LivingEntity target = (LivingEntity) event.getEntity();
|
||||
double damage = data.getDamage();
|
||||
// Calculate custom base bow damage
|
||||
double baseDamage = data.getDamage();
|
||||
|
||||
// Apply power vanilla enchant
|
||||
if (projectile instanceof Arrow && data.getSourceItem().getItem().hasItemMeta()
|
||||
&& data.getSourceItem().getItem().getItemMeta().getEnchants().containsKey(Enchantment.ARROW_DAMAGE))
|
||||
damage *= 1.25 + (.25 * data.getSourceItem().getItem().getItemMeta().getEnchantLevel(Enchantment.ARROW_DAMAGE));
|
||||
baseDamage *= 1.25 + (.25 * data.getSourceItem().getItem().getItemMeta().getEnchantLevel(Enchantment.ARROW_DAMAGE));
|
||||
|
||||
event.setDamage(baseDamage);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onHitEffects(PlayerAttackEvent event) {
|
||||
if (!(event.getAttack() instanceof ProjectileAttackMetadata projAttack))
|
||||
return;
|
||||
|
||||
final ProjectileData data = projectiles.get(projAttack.getProjectile().getEntityId());
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
// Apply MMOItems specific modifications
|
||||
if (data.isCustomWeapon())
|
||||
data.applyPotionEffects(target);
|
||||
|
||||
event.setDamage(event.getDamage() + damage - data.getCachedInitialDamage());
|
||||
|
||||
// Remove projectile if it has no piercing anymore
|
||||
if (!(projectile instanceof AbstractArrow) || ((AbstractArrow) projectile).getPierceLevel() <= 1)
|
||||
unregisterCustomProjectile(projectile);
|
||||
data.applyPotionEffects(event.getEntity());
|
||||
}
|
||||
|
||||
// Unregister custom projectiles from the map
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void unregisterOnBlockHit(ProjectileHitEvent event) {
|
||||
if (event.getHitBlock() != null)
|
||||
projectiles.remove(event.getEntity().getEntityId());
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void unregisterProjectileData(ProjectileHitEvent event) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, () -> unregisterCustomProjectile(event.getEntity()));
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void unregisterOnEntityHit(EntityDeathEvent event) {
|
||||
projectiles.remove(event.getEntity().getEntityId());
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void unregisterEntityData(EntityDeathEvent event) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, () -> unregisterCustomEntity(event.getEntity()));
|
||||
}
|
||||
}
|
@ -26,7 +26,10 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public class PlayerListener implements Listener {
|
||||
private final Map<Player, ArrayList<ItemStack>> deathItems = new HashMap<>();
|
||||
@ -144,14 +147,14 @@ public class PlayerListener implements Listener {
|
||||
PlayerData playerData = PlayerData.get((Player) event.getEntity().getShooter());
|
||||
|
||||
if (type != null) {
|
||||
Weapon weapon = new Weapon(playerData, nbtItem);
|
||||
final Weapon weapon = new Weapon(playerData, nbtItem);
|
||||
if (!weapon.checkItemRequirements() || !weapon.checkAndApplyWeaponCosts()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MMOItems.plugin.getEntities().registerCustomProjectile(nbtItem, playerData.getStats().newTemporary(EquipmentSlot.fromBukkit(item.getSlot())), event.getEntity(), type != null, 1);
|
||||
MMOItems.plugin.getEntities().registerCustomProjectile(nbtItem, playerData.getStats().newTemporary(EquipmentSlot.fromBukkit(item.getSlot())), event.getEntity(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user