crossbow!
This commit is contained in:
@@ -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<String>): 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<String>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
autocrossbow.use:
|
||||
description: Allows use of the AutoCrossbow command
|
||||
default: op
|
||||
|
||||
Reference in New Issue
Block a user