new system ; now you can cast in the air! and also pull towards it!

This commit is contained in:
rattatwinko
2025-05-03 15:02:14 +02:00
parent d683bc1a9e
commit 3d3b6a001b

View File

@@ -26,6 +26,7 @@ class GrapplingHook : JavaPlugin(), Listener {
private val grapplingHookKey = NamespacedKey(this, "grappling_hook")
private val cooldowns = HashMap<UUID, Long>()
private val recentlyGrappled = HashSet<UUID>()
private val activeHooks = HashMap<UUID, FishHook>()
private var cooldownSeconds = 2
private var pullStrength = 1.5
@@ -33,6 +34,8 @@ class GrapplingHook : JavaPlugin(), Listener {
private var maxDistance = 30.0
private var showParticles = true
private var hookSpeed = 2.5
private var airGrappleStrength = 1.2
private var airGrappleEnabled = true
override fun onEnable() {
server.pluginManager.registerEvents(this, this)
@@ -58,6 +61,8 @@ class GrapplingHook : JavaPlugin(), Listener {
writer.println("max-distance: 30.0")
writer.println("show-particles: true")
writer.println("hook-speed: 2.5")
writer.println("air-grapple-enabled: true")
writer.println("air-grapple-strength: 1.2")
writer.close()
} catch (e: Exception) {
logger.severe("Could not create config.yml: ${e.message}")
@@ -77,6 +82,8 @@ class GrapplingHook : JavaPlugin(), Listener {
maxDistance = config.getDouble("max-distance", 30.0)
showParticles = config.getBoolean("show-particles", true)
hookSpeed = config.getDouble("hook-speed", 2.5)
airGrappleEnabled = config.getBoolean("air-grapple-enabled", true)
airGrappleStrength = config.getDouble("air-grapple-strength", 1.2)
}
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
@@ -139,6 +146,7 @@ class GrapplingHook : JavaPlugin(), Listener {
val lore = ArrayList<String>()
lore.add("${ChatColor.GRAY}Right-click to launch the hook")
lore.add("${ChatColor.GRAY}Pull yourself to the hook location")
lore.add("${ChatColor.YELLOW}Right-click while hook is in air for a quick boost!")
meta?.lore = lore
meta?.isUnbreakable = true
@@ -167,7 +175,7 @@ class GrapplingHook : JavaPlugin(), Listener {
val player = event.player
val item = player.inventory.itemInMainHand
if (!isGrapplingHook(item)) return
if (!isGrapplingHook(item) && !isGrapplingHook(player.inventory.itemInOffHand)) return
when (event.state) {
PlayerFishEvent.State.FISHING -> {
@@ -185,6 +193,9 @@ class GrapplingHook : JavaPlugin(), Listener {
cooldowns[uuid] = System.currentTimeMillis()
event.hook.velocity = event.hook.velocity.multiply(hookSpeed)
player.world.playSound(player.location, Sound.ENTITY_ARROW_SHOOT, 1.0f, 1.0f)
// Store the active hook for air grapples
activeHooks[uuid] = event.hook
}
PlayerFishEvent.State.IN_GROUND, PlayerFishEvent.State.CAUGHT_ENTITY -> {
@@ -196,29 +207,47 @@ class GrapplingHook : JavaPlugin(), Listener {
return
}
val direction = hook.location.toVector().subtract(player.location.toVector())
var adjustedPullStrength = pullStrength
if (distance > 15.0) {
adjustedPullStrength *= 1.0 + ((distance - 15.0) / 15.0)
}
// Standard grapple when the hook hits something
pullPlayerTowards(player, hook.location.toVector(), pullStrength, distance)
direction.normalize().multiply(adjustedPullStrength)
direction.y = Math.max(0.4, direction.y)
player.velocity = direction
// Clean up
activeHooks.remove(player.uniqueId)
}
if (preventFallDamage) {
recentlyGrappled.add(player.uniqueId)
object : BukkitRunnable() {
override fun run() {
recentlyGrappled.remove(player.uniqueId)
PlayerFishEvent.State.REEL_IN -> {
// This is triggered when player right-clicks while the hook is in the air
if (airGrappleEnabled && activeHooks.containsKey(player.uniqueId)) {
val hook = activeHooks[player.uniqueId]
if (hook != null && !hook.isDead) {
// Air grapple logic - boost in the direction the player is looking
val lookDirection = player.location.direction
val boost = lookDirection.normalize().multiply(airGrappleStrength)
// Add a slight upward boost to prevent players from smashing into the ground
if (boost.y < 0.2) {
boost.y = 0.2
}
}.runTaskLater(this, 100L)
}
player.world.playSound(player.location, Sound.ENTITY_ZOMBIE_INFECT, 1.0f, 2.0f)
player.velocity = boost
if (showParticles) {
showGrapplingParticles(player, hook)
if (preventFallDamage) {
recentlyGrappled.add(player.uniqueId)
object : BukkitRunnable() {
override fun run() {
recentlyGrappled.remove(player.uniqueId)
}
}.runTaskLater(this, 100L)
}
player.world.playSound(player.location, Sound.ENTITY_BAT_TAKEOFF, 1.0f, 1.5f)
if (showParticles) {
showAirGrappleParticles(player)
}
}
// Clean up
activeHooks.remove(player.uniqueId)
}
}
@@ -226,6 +255,34 @@ class GrapplingHook : JavaPlugin(), Listener {
}
}
private fun pullPlayerTowards(player: Player, targetLocation: Vector, strength: Double, distance: Double) {
val direction = targetLocation.subtract(player.location.toVector())
var adjustedPullStrength = strength
if (distance > 15.0) {
adjustedPullStrength *= 1.0 + ((distance - 15.0) / 15.0)
}
direction.normalize().multiply(adjustedPullStrength)
direction.y = Math.max(0.4, direction.y)
player.velocity = direction
if (preventFallDamage) {
recentlyGrappled.add(player.uniqueId)
object : BukkitRunnable() {
override fun run() {
recentlyGrappled.remove(player.uniqueId)
}
}.runTaskLater(this, 100L)
}
player.world.playSound(player.location, Sound.ENTITY_ZOMBIE_INFECT, 1.0f, 2.0f)
if (showParticles) {
showGrapplingParticles(player, targetLocation.toLocation(player.world))
}
}
@EventHandler
fun onEntityDamage(event: EntityDamageEvent) {
if (event.entity !is Player) return
@@ -241,25 +298,25 @@ class GrapplingHook : JavaPlugin(), Listener {
}
}
private fun isGrapplingHook(item: ItemStack): Boolean {
if (item.type != Material.FISHING_ROD) return false
private fun isGrapplingHook(item: ItemStack?): Boolean {
if (item == null || item.type != Material.FISHING_ROD) return false
val meta = item.itemMeta ?: return false
return meta.persistentDataContainer.has(grapplingHookKey, PersistentDataType.BYTE)
}
private fun showGrapplingParticles(player: Player, hook: FishHook) {
private fun showGrapplingParticles(player: Player, targetLocation: org.bukkit.Location) {
object : BukkitRunnable() {
var distance = player.location.distance(hook.location)
var distance = player.location.distance(targetLocation)
var traveled = 0.0
val particleSpacing = 0.3
override fun run() {
if (traveled >= distance || !player.isOnline || hook.isDead) {
if (traveled >= distance || !player.isOnline) {
cancel()
return
}
val direction = hook.location.toVector().subtract(player.location.toVector()).normalize()
val direction = targetLocation.toVector().subtract(player.location.toVector()).normalize()
val particleLocation = player.location.clone().add(direction.multiply(traveled))
player.world.spawnParticle(Particle.CRIT, particleLocation, 2, 0.05, 0.05, 0.05, 0.01)
@@ -271,4 +328,33 @@ class GrapplingHook : JavaPlugin(), Listener {
}
}.runTaskTimer(this, 0L, 1L)
}
}
private fun showAirGrappleParticles(player: Player) {
// Create a swirl of particles around the player
object : BukkitRunnable() {
var counter = 0
override fun run() {
if (counter >= 10 || !player.isOnline) {
cancel()
return
}
// Create a circular pattern
for (i in 0 until 8) {
val angle = i * Math.PI / 4
val x = Math.cos(angle) * 0.7
val z = Math.sin(angle) * 0.7
val particleLocation = player.location.clone().add(x, counter * 0.1, z)
player.world.spawnParticle(Particle.CLOUD, particleLocation, 1, 0.05, 0.05, 0.05, 0.01)
if (i % 2 == 0) {
player.world.spawnParticle(Particle.CRIT, particleLocation, 1, 0.05, 0.05, 0.05, 0.01)
}
}
counter++
}
}.runTaskTimer(this, 0L, 2L)
}
}