Search in sources :

Example 1 with EntityShootBowEvent

use of org.bukkit.event.entity.EntityShootBowEvent in project Glowstone by GlowstoneMC.

the class ItemBow method endUse.

@Override
public void endUse(GlowPlayer player, ItemStack bow) {
    // Check arrows again, since plugins may have changed the inventory while the bow was drawn
    Optional<GlowInventorySlot> maybeArrow = findArrow(player);
    GlowInventorySlot slot = null;
    ItemStack arrow = null;
    final Material arrowType;
    Projectile launchedProjectile = null;
    boolean consumeArrow = false;
    if (maybeArrow.isPresent()) {
        slot = maybeArrow.get();
        arrow = slot.getItem();
        arrowType = arrow.getType();
        consumeArrow = (player.getGameMode() != GameMode.CREATIVE);
    } else if (player.getGameMode() == GameMode.CREATIVE) {
        // Can fire without arrows in Creative
        arrowType = Material.ARROW;
        consumeArrow = false;
    } else {
        arrowType = Material.AIR;
    }
    switch(arrowType) {
        case ARROW:
            if (bow.containsEnchantment(Enchantment.ARROW_INFINITE)) {
                consumeArrow = false;
            }
            launchedProjectile = player.launchProjectile(Arrow.class);
            break;
        case TIPPED_ARROW:
            launchedProjectile = player.launchProjectile(TippedArrow.class);
            GlowTippedArrow launchedTippedArrow = (GlowTippedArrow) launchedProjectile;
            launchedTippedArrow.copyFrom((PotionMeta) arrow.getItemMeta());
            break;
        case SPECTRAL_ARROW:
            launchedProjectile = player.launchProjectile(SpectralArrow.class);
            break;
        case AIR:
            // Not in creative mode and have no arrow
            break;
        default:
            GlowServer.logger.log(Level.SEVERE, () -> String.format("Attempt to fire %s from a bow", arrowType));
    }
    if (launchedProjectile != null) {
        float chargeFraction = (TICKS_TO_FULLY_CHARGE - Floats.constrainToRange(player.getUsageTime(), 0.0f, TICKS_TO_FULLY_CHARGE)) / TICKS_TO_FULLY_CHARGE;
        EntityShootBowEvent event = new EntityShootBowEvent(player, bow, arrow, launchedProjectile, chargeFraction);
        event.setConsumeArrow(consumeArrow);
        event = EventFactory.getInstance().callEvent(event);
        consumeArrow = event.getConsumeArrow();
        // TODO: Call for Skeleton firing too when implemented
        if (event.isCancelled()) {
            launchedProjectile.remove();
        } else {
            chargeFraction = event.getForce();
            launchedProjectile = (Projectile) event.getProjectile();
            if (consumeArrow) {
                int amount = arrow.getAmount();
                if (amount <= 1) {
                    arrow = InventoryUtil.createEmptyStack();
                } else {
                    arrow.setAmount(amount - 1);
                }
                slot.setItem(arrow);
            }
            double damage = Math.max(1.0, MAX_BASE_DAMAGE + (chargeFraction == 1.0 && ThreadLocalRandom.current().nextFloat() >= 0.8 ? 1 : 0) * chargeFraction * (1 + 0.25 * bow.getEnchantmentLevel(Enchantment.ARROW_DAMAGE)));
            launchedProjectile.setVelocity(player.getEyeLocation().getDirection().multiply(Math.max(5, chargeFraction * MAX_SPEED)));
            if (bow.containsEnchantment(Enchantment.ARROW_FIRE)) {
                // Arrow will burn as long as it's in flight, unless extinguished by water
                launchedProjectile.setFireTicks(Integer.MAX_VALUE);
            }
            // Plugin may change projectile to non arrow.
            if (launchedProjectile instanceof Arrow) {
                Arrow launchedArrow = (Arrow) launchedProjectile;
                launchedArrow.setDamage(damage);
                launchedArrow.setKnockbackStrength(bow.getEnchantmentLevel(Enchantment.ARROW_KNOCKBACK));
                // 20% crit chance
                if (ThreadLocalRandom.current().nextDouble() < 0.2) {
                    launchedArrow.setCritical(true);
                }
            }
            if (player.getInventory().getItemInMainHand().getType() == Material.BOW) {
                player.getInventory().setItemInMainHand(InventoryUtil.damageItem(player, bow));
            } else {
                player.getInventory().setItemInOffHand(InventoryUtil.damageItem(player, bow));
            }
        }
    }
    player.setUsageItem(null);
    player.setUsageTime(0);
}
Also used : Arrow(org.bukkit.entity.Arrow) SpectralArrow(org.bukkit.entity.SpectralArrow) TippedArrow(org.bukkit.entity.TippedArrow) GlowTippedArrow(net.glowstone.entity.projectile.GlowTippedArrow) EntityShootBowEvent(org.bukkit.event.entity.EntityShootBowEvent) Material(org.bukkit.Material) SpectralArrow(org.bukkit.entity.SpectralArrow) Projectile(org.bukkit.entity.Projectile) TippedArrow(org.bukkit.entity.TippedArrow) GlowTippedArrow(net.glowstone.entity.projectile.GlowTippedArrow) GlowTippedArrow(net.glowstone.entity.projectile.GlowTippedArrow) GlowInventorySlot(net.glowstone.inventory.GlowInventorySlot) ItemStack(org.bukkit.inventory.ItemStack)

Aggregations

GlowTippedArrow (net.glowstone.entity.projectile.GlowTippedArrow)1 GlowInventorySlot (net.glowstone.inventory.GlowInventorySlot)1 Material (org.bukkit.Material)1 Arrow (org.bukkit.entity.Arrow)1 Projectile (org.bukkit.entity.Projectile)1 SpectralArrow (org.bukkit.entity.SpectralArrow)1 TippedArrow (org.bukkit.entity.TippedArrow)1 EntityShootBowEvent (org.bukkit.event.entity.EntityShootBowEvent)1 ItemStack (org.bukkit.inventory.ItemStack)1