feat: Improve Glider item user feedback with action bar messages, sounds, and particles, add a detailed gliding status display, and update Grappling Hook lore with tier-based stats.
This commit is contained in:
parent
7cc8ccc395
commit
283961652c
|
|
@ -131,15 +131,21 @@ class GliderItem : SpecialItem("glider") {
|
|||
val item = event.item ?: return
|
||||
val tier = SpecialItem.getTier(item)
|
||||
|
||||
|
||||
if (!canDeploy(player)) {
|
||||
player.sendMessage(Component.text("グライダーを展開するには空中にいる必要があります!", NamedTextColor.RED))
|
||||
player.sendActionBar(
|
||||
Component.text("✗ ", NamedTextColor.RED)
|
||||
.append(Component.text("空中にいる必要があります!", NamedTextColor.YELLOW))
|
||||
)
|
||||
player.playSound(player.location, Sound.ENTITY_VILLAGER_NO, 0.5f, 1.0f)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (isBroken(item)) {
|
||||
player.sendMessage(Component.text("グライダーが壊れています!修理が必要です。", NamedTextColor.RED))
|
||||
player.sendActionBar(
|
||||
Component.text("⚠ ", NamedTextColor.RED)
|
||||
.append(Component.text("グライダーが壊れています!", NamedTextColor.YELLOW))
|
||||
)
|
||||
player.playSound(player.location, Sound.ENTITY_ITEM_BREAK, 0.5f, 0.8f)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -147,14 +153,47 @@ class GliderItem : SpecialItem("glider") {
|
|||
val isEnabled = meta.persistentDataContainer.get(KEY_GLIDER_ENABLED, PersistentDataType.BOOLEAN) ?: false
|
||||
|
||||
if (isEnabled) {
|
||||
|
||||
disableGlider(player, item)
|
||||
player.sendMessage(Component.text("グライダーを収納しました", NamedTextColor.YELLOW))
|
||||
} else {
|
||||
|
||||
player.sendActionBar(
|
||||
Component.text("⬇ ", NamedTextColor.GRAY)
|
||||
.append(Component.text("グライダー収納", NamedTextColor.YELLOW))
|
||||
)
|
||||
player.playSound(player.location, Sound.ITEM_ARMOR_EQUIP_ELYTRA, 0.8f, 0.8f)
|
||||
player.playSound(player.location, Sound.BLOCK_WOOL_PLACE, 1.0f, 1.2f)
|
||||
|
||||
player.world.spawnParticle(
|
||||
Particle.CLOUD,
|
||||
player.location.add(0.0, 1.5, 0.0),
|
||||
10,
|
||||
0.3, 0.3, 0.3,
|
||||
0.02
|
||||
)
|
||||
} else {
|
||||
enableGlider(player, item)
|
||||
player.sendMessage(Component.text("グライダーを展開しました!", NamedTextColor.GREEN))
|
||||
player.playSound(player.location, Sound.ITEM_ARMOR_EQUIP_ELYTRA, 1.0f, 1.0f)
|
||||
|
||||
player.sendActionBar(
|
||||
Component.text("⬆ ", NamedTextColor.GREEN)
|
||||
.append(Component.text("グライダー展開!", NamedTextColor.AQUA))
|
||||
.append(Component.text(" [Tier ${tier.level}]", tier.color))
|
||||
)
|
||||
player.playSound(player.location, Sound.ITEM_ARMOR_EQUIP_ELYTRA, 1.0f, 1.2f)
|
||||
player.playSound(player.location, Sound.ENTITY_PHANTOM_FLAP, 0.7f, 1.5f)
|
||||
|
||||
player.world.spawnParticle(
|
||||
Particle.CLOUD,
|
||||
player.location.add(0.0, 1.5, 0.0),
|
||||
20,
|
||||
0.5, 0.3, 0.5,
|
||||
0.05
|
||||
)
|
||||
player.world.spawnParticle(
|
||||
Particle.FIREWORK,
|
||||
player.location.add(0.0, 1.5, 0.0),
|
||||
5,
|
||||
0.3, 0.3, 0.3,
|
||||
0.02
|
||||
)
|
||||
}
|
||||
|
||||
event.isCancelled = true
|
||||
|
|
@ -206,6 +245,10 @@ class GliderItem : SpecialItem("glider") {
|
|||
spawnGlidingParticles(player)
|
||||
}
|
||||
|
||||
if (state.ticksGliding % 10 == 0) {
|
||||
updateGliderActionBar(player, item, tier, state)
|
||||
}
|
||||
|
||||
|
||||
val hungerInterval = TIER_HUNGER_INTERVAL[tier] ?: 80
|
||||
if (state.ticksGliding % hungerInterval == 0) {
|
||||
|
|
@ -218,6 +261,43 @@ class GliderItem : SpecialItem("glider") {
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateGliderActionBar(player: Player, item: ItemStack, tier: Tier, state: GliderState) {
|
||||
val meta = item.itemMeta
|
||||
val currentDurability = if (meta is Damageable) {
|
||||
val maxDamage = TIER_MAX_DURABILITY[tier] ?: 64
|
||||
maxDamage - meta.damage
|
||||
} else {
|
||||
0
|
||||
}
|
||||
val maxDurability = TIER_MAX_DURABILITY[tier] ?: 64
|
||||
val durabilityPercent = (currentDurability.toDouble() / maxDurability * 100).toInt()
|
||||
|
||||
val durabilityColor = when {
|
||||
durabilityPercent > 66 -> NamedTextColor.GREEN
|
||||
durabilityPercent > 33 -> NamedTextColor.YELLOW
|
||||
else -> NamedTextColor.RED
|
||||
}
|
||||
|
||||
val altitude = player.location.y.toInt()
|
||||
val velocity = player.velocity
|
||||
val speed = sqrt(velocity.x * velocity.x + velocity.z * velocity.z)
|
||||
|
||||
player.sendActionBar(
|
||||
Component.text("✈ ", NamedTextColor.AQUA)
|
||||
.append(Component.text("滑空中 ", NamedTextColor.WHITE))
|
||||
.append(Component.text("| ", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text("速度: ", NamedTextColor.GRAY))
|
||||
.append(Component.text(String.format("%.1f", speed * 20), tier.color))
|
||||
.append(Component.text(" m/s ", NamedTextColor.GRAY))
|
||||
.append(Component.text("| ", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text("高度: ", NamedTextColor.GRAY))
|
||||
.append(Component.text("${altitude}m ", NamedTextColor.YELLOW))
|
||||
.append(Component.text("| ", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text("耐久: ", NamedTextColor.GRAY))
|
||||
.append(Component.text("${durabilityPercent}%", durabilityColor))
|
||||
)
|
||||
}
|
||||
|
||||
private fun applyGlidingPhysics(player: Player, tier: Tier) {
|
||||
val velocity = player.velocity
|
||||
val fallSpeed = TIER_FALL_SPEED[tier] ?: -0.05
|
||||
|
|
@ -255,7 +335,6 @@ class GliderItem : SpecialItem("glider") {
|
|||
maxOf(velocity.y, fallSpeed),
|
||||
horizontalDir.z * newHorizontalSpeed
|
||||
)
|
||||
player.sendActionBar(Component.text("Gliding at ${newHorizontalSpeed} m/s", NamedTextColor.GREEN))
|
||||
|
||||
player.velocity = newVelocity
|
||||
}
|
||||
|
|
@ -290,6 +369,15 @@ class GliderItem : SpecialItem("glider") {
|
|||
|
||||
|
||||
player.velocity = Vector(player.velocity.x, UPDRAFT_BOOST, player.velocity.z)
|
||||
|
||||
player.playSound(player.location, Sound.BLOCK_FIRE_AMBIENT, 0.3f, 1.5f)
|
||||
|
||||
player.sendActionBar(
|
||||
Component.text("🔥 ", NamedTextColor.GOLD)
|
||||
.append(Component.text("上昇気流!", NamedTextColor.YELLOW))
|
||||
.append(Component.text(" ⬆", NamedTextColor.GREEN))
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -307,6 +395,15 @@ class GliderItem : SpecialItem("glider") {
|
|||
continue
|
||||
}
|
||||
player.velocity = Vector(player.velocity.x, UPDRAFT_BOOST, player.velocity.z)
|
||||
|
||||
player.playSound(player.location, Sound.BLOCK_FIRE_AMBIENT, 0.3f, 1.5f)
|
||||
|
||||
player.sendActionBar(
|
||||
Component.text("🔥 ", NamedTextColor.GOLD)
|
||||
.append(Component.text("上昇気流!", NamedTextColor.YELLOW))
|
||||
.append(Component.text(" ⬆", NamedTextColor.GREEN))
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -326,15 +423,40 @@ class GliderItem : SpecialItem("glider") {
|
|||
val currentDamage = meta.damage
|
||||
|
||||
if (currentDamage >= maxDamage - 1) {
|
||||
|
||||
meta.damage = maxDamage
|
||||
item.itemMeta = meta
|
||||
disableGlider(player, item)
|
||||
|
||||
player.playSound(player.location, Sound.ENTITY_ITEM_BREAK, 1.0f, 1.0f)
|
||||
player.sendMessage(Component.text("グライダーが壊れました!", NamedTextColor.RED))
|
||||
player.playSound(player.location, Sound.BLOCK_WOOL_BREAK, 1.0f, 0.5f)
|
||||
|
||||
player.sendActionBar(
|
||||
Component.text("💥 ", NamedTextColor.RED)
|
||||
.append(Component.text("グライダーが壊れました!", NamedTextColor.DARK_RED))
|
||||
)
|
||||
|
||||
player.world.spawnParticle(
|
||||
Particle.ITEM,
|
||||
player.location.add(0.0, 1.5, 0.0),
|
||||
30,
|
||||
0.5, 0.5, 0.5,
|
||||
0.1,
|
||||
ItemStack(Material.PHANTOM_MEMBRANE)
|
||||
)
|
||||
} else {
|
||||
meta.damage = currentDamage + 1
|
||||
item.itemMeta = meta
|
||||
|
||||
val durabilityPercent = ((maxDamage - currentDamage - 1).toDouble() / maxDamage * 100).toInt()
|
||||
|
||||
if (durabilityPercent <= 20 && currentDamage % 10 == 0) {
|
||||
player.sendActionBar(
|
||||
Component.text("⚠ ", NamedTextColor.YELLOW)
|
||||
.append(Component.text("耐久値低下! ", NamedTextColor.RED))
|
||||
.append(Component.text("残り${durabilityPercent}%", NamedTextColor.GOLD))
|
||||
)
|
||||
player.playSound(player.location, Sound.BLOCK_ANVIL_LAND, 0.3f, 2.0f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,25 @@ class GrapplingItem : SpecialItem("grappling_hook") {
|
|||
val item = ItemStack(Material.FISHING_ROD)
|
||||
val meta = item.itemMeta ?: return item
|
||||
|
||||
meta.displayName(Component.text("Grappling Hook", tier.color))
|
||||
val speed = 1.0 + (tier.level * 0.4)
|
||||
val efficiency = 1.0 + (tier.level * 0.1)
|
||||
|
||||
val speedStars = "★".repeat(tier.level) + "☆".repeat(5 - tier.level)
|
||||
val efficiencyStars = "★".repeat(tier.level) + "☆".repeat(5 - tier.level)
|
||||
|
||||
meta.displayName(Component.text("グラップリングフック", tier.color))
|
||||
meta.lore(listOf(
|
||||
Component.text("Cast and reel in to pull yourself!", NamedTextColor.GRAY),
|
||||
Component.text("Tier: ${tier.level}", tier.color)
|
||||
Component.empty(),
|
||||
Component.text("投げて引き寄せられる!", NamedTextColor.GRAY),
|
||||
Component.text("落下ダメージを軽減", NamedTextColor.GRAY),
|
||||
Component.empty(),
|
||||
Component.text("【性能】", NamedTextColor.WHITE),
|
||||
Component.text("ティア: ${tier.name}", tier.color),
|
||||
Component.text("引き寄せ速度: $speedStars", NamedTextColor.AQUA),
|
||||
Component.text("燃費: $efficiencyStars", NamedTextColor.GREEN),
|
||||
Component.empty(),
|
||||
Component.text("右クリックで投げる", NamedTextColor.YELLOW),
|
||||
Component.text("もう一度右クリックで引き寄せ", NamedTextColor.YELLOW)
|
||||
))
|
||||
|
||||
item.itemMeta = meta
|
||||
|
|
@ -27,11 +42,11 @@ class GrapplingItem : SpecialItem("grappling_hook") {
|
|||
|
||||
override fun onFish(event: PlayerFishEvent) {
|
||||
val hook = event.hook
|
||||
val player = event.player
|
||||
|
||||
val isStuck = hook.persistentDataContainer.has(KEY_HOOK_STUCK, org.bukkit.persistence.PersistentDataType.BYTE)
|
||||
|
||||
if (event.state == PlayerFishEvent.State.REEL_IN && isStuck) {
|
||||
val player = event.player
|
||||
val playerLoc = player.location
|
||||
val hookLoc = hook.location
|
||||
|
||||
|
|
@ -53,6 +68,30 @@ class GrapplingItem : SpecialItem("grappling_hook") {
|
|||
val hungerCost = (velocity.length() * hungerCostBase / efficiency).toInt().coerceAtLeast(1)
|
||||
|
||||
player.foodLevel = (player.foodLevel - hungerCost).coerceAtLeast(0)
|
||||
|
||||
player.playSound(playerLoc, org.bukkit.Sound.ENTITY_FISHING_BOBBER_RETRIEVE, 1.0f, 1.2f)
|
||||
player.playSound(playerLoc, org.bukkit.Sound.ENTITY_ENDER_DRAGON_FLAP, 0.5f, 1.5f)
|
||||
|
||||
val distance = playerLoc.distance(hookLoc)
|
||||
player.sendActionBar(
|
||||
Component.text("引き寄せ中! ", NamedTextColor.AQUA)
|
||||
.append(Component.text("距離: ${String.format("%.1f", distance)}m", NamedTextColor.WHITE))
|
||||
.append(Component.text(" | ", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text("速度: ${String.format("%.1f", speed)}x", tier.color))
|
||||
)
|
||||
|
||||
for (i in 0..5) {
|
||||
val particleLoc = playerLoc.clone().add(
|
||||
vector.clone().normalize().multiply(i * distance / 5.0)
|
||||
)
|
||||
player.world.spawnParticle(
|
||||
org.bukkit.Particle.CRIT,
|
||||
particleLoc,
|
||||
3,
|
||||
0.1, 0.1, 0.1,
|
||||
0.0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (event.state == PlayerFishEvent.State.REEL_IN ||
|
||||
|
|
@ -71,8 +110,10 @@ class GrapplingItem : SpecialItem("grappling_hook") {
|
|||
val shooter = projectile.shooter
|
||||
|
||||
if (shooter is org.bukkit.entity.Player) {
|
||||
projectile.velocity = projectile.velocity.add(shooter.velocity)
|
||||
|
||||
projectile.velocity = projectile.velocity.add(shooter.velocity)
|
||||
shooter.playSound(shooter.location, org.bukkit.Sound.ENTITY_FISHING_BOBBER_THROW, 1.0f, 0.8f)
|
||||
shooter.playSound(shooter.location, org.bukkit.Sound.ENTITY_ARROW_SHOOT, 0.5f, 1.2f)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,9 +132,34 @@ class GrapplingItem : SpecialItem("grappling_hook") {
|
|||
stand.persistentDataContainer.set(KEY_ANCHOR_ID, org.bukkit.persistence.PersistentDataType.STRING, "grapple")
|
||||
}
|
||||
|
||||
|
||||
if (anchor.addPassenger(hook)) {
|
||||
hook.persistentDataContainer.set(KEY_HOOK_STUCK, org.bukkit.persistence.PersistentDataType.BYTE, 1)
|
||||
|
||||
location.world.playSound(location, org.bukkit.Sound.BLOCK_ANVIL_LAND, 0.5f, 2.0f)
|
||||
location.world.playSound(location, org.bukkit.Sound.BLOCK_CHAIN_PLACE, 1.0f, 1.5f)
|
||||
|
||||
location.world.spawnParticle(
|
||||
org.bukkit.Particle.ENCHANTED_HIT,
|
||||
location,
|
||||
15,
|
||||
0.2, 0.2, 0.2,
|
||||
0.1
|
||||
)
|
||||
location.world.spawnParticle(
|
||||
org.bukkit.Particle.SMOKE,
|
||||
location,
|
||||
5,
|
||||
0.1, 0.1, 0.1,
|
||||
0.02
|
||||
)
|
||||
|
||||
val shooter = hook.shooter
|
||||
if (shooter is org.bukkit.entity.Player) {
|
||||
shooter.sendActionBar(
|
||||
Component.text("✓ ", NamedTextColor.GREEN)
|
||||
.append(Component.text("フック固定!", NamedTextColor.WHITE))
|
||||
)
|
||||
}
|
||||
} else {
|
||||
anchor.remove()
|
||||
}
|
||||
|
|
@ -106,6 +172,8 @@ class GrapplingItem : SpecialItem("grappling_hook") {
|
|||
val player = event.entity
|
||||
if (player is org.bukkit.entity.Player) {
|
||||
val item = player.inventory.itemInMainHand
|
||||
if (!SpecialItem.isSpecialItem(item) || SpecialItem.getId(item) != "grappling_hook") return
|
||||
|
||||
val tier = SpecialItem.getTier(item)
|
||||
|
||||
val originalDamage = event.damage
|
||||
|
|
@ -119,14 +187,31 @@ class GrapplingItem : SpecialItem("grappling_hook") {
|
|||
if (player.foodLevel >= totalHungerCost) {
|
||||
player.foodLevel = (player.foodLevel - totalHungerCost).coerceAtLeast(0)
|
||||
event.damage = reducedDamage
|
||||
|
||||
player.playSound(player.location, org.bukkit.Sound.BLOCK_WOOL_FALL, 1.0f, 0.8f)
|
||||
player.playSound(player.location, org.bukkit.Sound.ENTITY_PLAYER_ATTACK_NODAMAGE, 0.5f, 1.5f)
|
||||
|
||||
player.sendActionBar(
|
||||
Component.text("🛡 ", NamedTextColor.GOLD)
|
||||
.append(Component.text("落下ダメージ軽減! ", NamedTextColor.GREEN))
|
||||
.append(Component.text("-${String.format("%.1f", damageToAbsorb)}❤", NamedTextColor.RED))
|
||||
)
|
||||
} else {
|
||||
val availableFood = player.foodLevel
|
||||
val damageWeCanAbsorb = availableFood / hungerCostPerDamage
|
||||
val damageWeCannotAbsorb = damageToAbsorb - damageWeCanAbsorb
|
||||
|
||||
player.foodLevel = 0
|
||||
|
||||
event.damage = reducedDamage + damageWeCannotAbsorb
|
||||
|
||||
if (damageWeCanAbsorb > 0) {
|
||||
player.playSound(player.location, org.bukkit.Sound.BLOCK_WOOL_FALL, 0.5f, 0.6f)
|
||||
player.sendActionBar(
|
||||
Component.text("⚠ ", NamedTextColor.YELLOW)
|
||||
.append(Component.text("空腹不足! ", NamedTextColor.RED))
|
||||
.append(Component.text("部分軽減のみ", NamedTextColor.GRAY))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user