From 61ed03b7d93d2be8cd33d143da93f700618da6db Mon Sep 17 00:00:00 2001 From: rattatwinko Date: Thu, 1 May 2025 22:38:34 +0200 Subject: [PATCH] crossbow! --- .../kotlin/org/AutoBow/autoBow/AutoBow.kt | 135 +++++++++++------- src/main/resources/plugin.yml | 20 +-- 2 files changed, 90 insertions(+), 65 deletions(-) diff --git a/src/main/kotlin/org/AutoBow/autoBow/AutoBow.kt b/src/main/kotlin/org/AutoBow/autoBow/AutoBow.kt index d9a6c27..d59238a 100644 --- a/src/main/kotlin/org/AutoBow/autoBow/AutoBow.kt +++ b/src/main/kotlin/org/AutoBow/autoBow/AutoBow.kt @@ -4,6 +4,7 @@ import org.bukkit.Bukkit import org.bukkit.ChatColor import org.bukkit.Material import org.bukkit.NamespacedKey +import org.bukkit.Particle import org.bukkit.Registry import org.bukkit.Sound import org.bukkit.command.Command @@ -18,31 +19,31 @@ import org.bukkit.event.entity.EntityShootBowEvent import org.bukkit.event.entity.ProjectileHitEvent import org.bukkit.inventory.ItemFlag import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.ItemMeta +import org.bukkit.inventory.meta.CrossbowMeta import org.bukkit.plugin.java.JavaPlugin -import org.bukkit.scheduler.BukkitRunnable import org.bukkit.util.Vector import java.util.* -class AutoBow : JavaPlugin(), Listener { +class AutoCrossbow : JavaPlugin(), Listener { companion object { private const val POWER_LEVEL = 10 private const val AUTO_AIM_DISTANCE = 100.0 // Maximum distance for auto-aim private const val KNOCKBACK_MULTIPLIER = 5.0 + private const val MULTISHOT_LEVEL = 5 // Super OP Multishot } override fun onEnable() { - logger.info("AutoBow plugin has been enabled!") + logger.info("AutoCrossbow plugin has been enabled!") server.pluginManager.registerEvents(this, this) - getCommand("autobow")?.setExecutor(AutoBowCommand()) + getCommand("autocrossbow")?.setExecutor(AutoCrossbowCommand()) // Register for arrow hit events to handle knockback server.pluginManager.registerEvents(object : Listener { @EventHandler fun onProjectileHit(event: ProjectileHitEvent) { val arrow = event.entity - if (arrow is Arrow && arrow.scoreboardTags.contains("autobow-knockback")) { + if (arrow is Arrow && arrow.scoreboardTags.contains("autocrossbow-knockback")) { // Apply knockback if our arrow hit an entity val hitEntity = event.hitEntity if (hitEntity is Player) { @@ -62,10 +63,10 @@ class AutoBow : JavaPlugin(), Listener { } override fun onDisable() { - logger.info("AutoBow plugin has been disabled!") + logger.info("AutoCrossbow plugin has been disabled!") } - private inner class AutoBowCommand : CommandExecutor { + private inner class AutoCrossbowCommand : CommandExecutor { override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array): Boolean { if (sender !is Player) { sender.sendMessage("${ChatColor.RED}This command can only be used by players!") @@ -80,12 +81,12 @@ class AutoBow : JavaPlugin(), Listener { return true } - // Create the auto bow - val autoBow = createAutoBow() + // Create the auto crossbow + val autoCrossbow = createAutoCrossbow() - // Give the player the bow - player.inventory.addItem(autoBow) - player.sendMessage("${ChatColor.GREEN}You have received the ${ChatColor.GOLD}Auto Bow${ChatColor.GREEN}! It will auto-aim at the nearest player.") + // Give the player the crossbow + player.inventory.addItem(autoCrossbow) + player.sendMessage("${ChatColor.GREEN}You have received the ${ChatColor.GOLD}Auto Crossbow${ChatColor.GREEN}! It will auto-aim at the nearest player.") // Also give arrows if player doesn't have any if (!player.inventory.contains(Material.ARROW)) { @@ -97,15 +98,15 @@ class AutoBow : JavaPlugin(), Listener { } } - private fun createAutoBow(): ItemStack { - val bow = ItemStack(Material.BOW) - val meta = bow.itemMeta ?: return bow + private fun createAutoCrossbow(): ItemStack { + val crossbow = ItemStack(Material.CROSSBOW) + val meta = crossbow.itemMeta as CrossbowMeta? ?: return crossbow // Set display name and lore - meta.setDisplayName("${ChatColor.GOLD}${ChatColor.BOLD}Auto-Aim Bow") + meta.setDisplayName("${ChatColor.GOLD}${ChatColor.BOLD}Auto-Aim Crossbow") val lore = ArrayList() - lore.add("${ChatColor.GRAY}This bow automatically aims at the nearest player.") + lore.add("${ChatColor.GRAY}This crossbow automatically aims at the nearest player.") lore.add("${ChatColor.RED}Extreme Knockback") lore.add("${ChatColor.RED}Power") lore.add("${ChatColor.DARK_PURPLE}OP Only Weapon") @@ -118,42 +119,48 @@ class AutoBow : JavaPlugin(), Listener { // Set the item to be unbreakable meta.isUnbreakable = true - bow.itemMeta = meta - - // Enchant the bow - FIXED LINES (122-124) + // Add enchantments (Power, Multishot, etc.) val powerEnchant = Registry.ENCHANTMENT.get(NamespacedKey.minecraft("power")) val infinityEnchant = Registry.ENCHANTMENT.get(NamespacedKey.minecraft("infinity")) val unbreakingEnchant = Registry.ENCHANTMENT.get(NamespacedKey.minecraft("unbreaking")) val knockbackEnchant = Registry.ENCHANTMENT.get(NamespacedKey.minecraft("knockback")) + val multishotEnchant = Registry.ENCHANTMENT.get(NamespacedKey.minecraft("multishot")) - if (powerEnchant != null) bow.addUnsafeEnchantment(powerEnchant, POWER_LEVEL) - if (infinityEnchant != null) bow.addUnsafeEnchantment(infinityEnchant, 1) - if (unbreakingEnchant != null) bow.addUnsafeEnchantment(unbreakingEnchant, 10) - if (knockbackEnchant != null) bow.addUnsafeEnchantment(knockbackEnchant, 10) + if (powerEnchant != null) crossbow.addUnsafeEnchantment(powerEnchant, POWER_LEVEL) + if (infinityEnchant != null) crossbow.addUnsafeEnchantment(infinityEnchant, 1) + if (unbreakingEnchant != null) crossbow.addUnsafeEnchantment(unbreakingEnchant, 10) + if (knockbackEnchant != null) crossbow.addUnsafeEnchantment(knockbackEnchant, 10) + if (multishotEnchant != null) crossbow.addUnsafeEnchantment(multishotEnchant, MULTISHOT_LEVEL) - return bow + // Set the custom meta to the item + crossbow.itemMeta = meta + + return crossbow } @EventHandler - fun onBowShoot(event: EntityShootBowEvent) { + fun onCrossbowShoot(event: EntityShootBowEvent) { if (event.entity !is Player) { return } val shooter = event.entity as Player - val bow = event.bow ?: return + val crossbow = event.bow ?: return - // Check if it's our special bow - if (bow.hasItemMeta() && bow.itemMeta?.hasDisplayName() == true && - bow.itemMeta?.displayName == "${ChatColor.GOLD}${ChatColor.BOLD}Auto-Aim Bow") { + // Check if it's our special crossbow + if (crossbow.hasItemMeta() && crossbow.itemMeta?.hasDisplayName() == true && + crossbow.itemMeta?.displayName == "${ChatColor.GOLD}${ChatColor.BOLD}Auto-Aim Crossbow") { - // Cancel the original arrow + // Cancel the original crossbow shot event.isCancelled = true + // Show particle effects when the crossbow is fired + shooter.world.spawnParticle(Particle.FIREWORK, shooter.location, 50, 0.5, 1.0, 0.5, 0.1) + // Find the nearest player val nearestPlayer = Bukkit.getOnlinePlayers() - .filter { it != shooter } - .minByOrNull { it.location.distanceSquared(shooter.location) } + .filter { it != shooter } + .minByOrNull { it.location.distanceSquared(shooter.location) } if (nearestPlayer != null) { val distance = shooter.location.distance(nearestPlayer.location) @@ -163,39 +170,57 @@ class AutoBow : JavaPlugin(), Listener { // Calculate the vector from the shooter to the target, accounting for movement and gravity val direction = calculateInterceptVector(shooter, nearestPlayer) - // Spawn a new arrow with the calculated direction - val arrow = shooter.launchProjectile(Arrow::class.java, direction) - arrow.velocity = direction.multiply(2.0) // Increase arrow speed - arrow.isCritical = true - arrow.fireTicks = 100 // Set arrow on fire for visual effect + // Spawn multiple arrows with the calculated direction (multishot effect) + for (i in 0 until 3) { + val arrow = shooter.launchProjectile(Arrow::class.java, direction.add(Vector(Math.random() * 0.2 - 0.1, 0.0, Math.random() * 0.2 - 0.1))) + arrow.velocity = direction.multiply(2.0) + arrow.isCritical = true + arrow.fireTicks = 100 // Set arrow on fire for visual effect - // Tag our arrow for custom knockback - arrow.addScoreboardTag("autobow-knockback") + // Tag our arrow for custom knockback + arrow.addScoreboardTag("autocrossbow-knockback") - // Set shooter as the arrow's shooter for proper damage attribution - arrow.shooter = shooter + // Set shooter as the arrow's shooter for proper damage attribution + arrow.shooter = shooter - // Play sound for feedback - shooter.playSound(shooter.location, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f) + // Play sound for feedback + shooter.playSound(shooter.location, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f) + } + + // Give the player an arrow after shooting + val arrowStack = ItemStack(Material.ARROW, 1) + shooter.inventory.addItem(arrowStack) shooter.sendMessage("${ChatColor.GREEN}Auto-aiming at ${ChatColor.RED}${nearestPlayer.name}${ChatColor.GREEN} (${Math.round(distance)} blocks away)") } else { shooter.sendMessage("${ChatColor.RED}No players within range for auto-aim!") - // Fire a normal arrow if no valid targets - val arrow = shooter.launchProjectile(Arrow::class.java) - arrow.velocity = shooter.location.direction.multiply(2.0) - arrow.isCritical = true - arrow.addScoreboardTag("autobow-knockback") + // Fire a normal shot with multiple arrows if no valid targets + for (i in 0 until 3) { + val arrow = shooter.launchProjectile(Arrow::class.java) + arrow.velocity = shooter.location.direction.multiply(2.0) + arrow.isCritical = true + arrow.addScoreboardTag("autocrossbow-knockback") + } + + // Give the player an arrow after shooting + val arrowStack = ItemStack(Material.ARROW, 1) + shooter.inventory.addItem(arrowStack) } } else { shooter.sendMessage("${ChatColor.RED}No players to auto-aim at!") - // Fire a normal arrow if no valid targets - val arrow = shooter.launchProjectile(Arrow::class.java) - arrow.velocity = shooter.location.direction.multiply(2.0) - arrow.isCritical = true - arrow.addScoreboardTag("autobow-knockback") + // Fire a normal shot with multiple arrows + for (i in 0 until 3) { + val arrow = shooter.launchProjectile(Arrow::class.java) + arrow.velocity = shooter.location.direction.multiply(2.0) + arrow.isCritical = true + arrow.addScoreboardTag("autocrossbow-knockback") + } + + // Give the player an arrow after shooting + val arrowStack = ItemStack(Material.ARROW, 1) + shooter.inventory.addItem(arrowStack) } } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 1f50d17..922f58d 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,15 +1,15 @@ -name: AutoBow +name: AutoCrossbow version: 1.0-SNAPSHOT -main: org.AutoBow.autoBow.AutoBow +main: org.AutoBow.autoBow.AutoCrossbow api-version: 1.18 -description: Gives OP players an auto-aiming bow with knockback +description: Gives OP players an auto-aiming crossbow with extreme knockback and multishot commands: - autobow: - description: Gives you an auto-aiming bow with extreme knockback - usage: /autobow - permission: autobow.use + autocrossbow: + description: Gives you an auto-aiming crossbow with extreme knockback and multishot + usage: /autocrossbow + permission: autocrossbow.use permission-message: You must be an operator to use this command! permissions: - autobow.use: - description: Allows use of the AutoBow command - default: op \ No newline at end of file + autocrossbow.use: + description: Allows use of the AutoCrossbow command + default: op