Consolidate ability particle utilities

Remove separate AbilityFeedback and AbilityParticles utilities and consolidate particle helpers into AbilityUtils. Add drawColoredParticleLine, drawGenericParticleLine and a spawnParticleLine helper to centralize line-particle logic (with Color/DustOptions support), and remove the old drawParticleLine and runForNearbyPlayers implementations. Update PuppetKit to use AbilityUtils.drawColoredParticleLine (and import Color) and remove the direct heart particle spawn. This refactors and centralizes particle/feedback behaviour for reuse and clearer APIs.
This commit is contained in:
TDSTOS
2026-04-12 07:39:57 +02:00
parent 4a28c58d2e
commit fd348a86e9
4 changed files with 43 additions and 114 deletions

View File

@@ -6,10 +6,12 @@ import club.mcscrims.speedhg.kit.Playstyle
import club.mcscrims.speedhg.kit.ability.AbilityResult
import club.mcscrims.speedhg.kit.ability.ActiveAbility
import club.mcscrims.speedhg.kit.ability.PassiveAbility
import club.mcscrims.speedhg.util.AbilityUtils
import club.mcscrims.speedhg.util.ItemBuilder
import club.mcscrims.speedhg.util.trans
import net.kyori.adventure.text.Component
import org.bukkit.Bukkit
import org.bukkit.Color
import org.bukkit.Material
import org.bukkit.Particle
import org.bukkit.Sound
@@ -274,6 +276,11 @@ class PuppetKit : Kit()
enemies.forEach { enemy ->
enemy.damage( capturedDrainDmg, player )
AbilityUtils.drawColoredParticleLine(
player.location,
enemy.location,
10, Color.RED
)
}
val remainingHealBudget = capturedMaxTotalHeal - totalHealedHp
@@ -285,11 +292,6 @@ class PuppetKit : Kit()
totalHealedHp += actualHeal
// Audio-visual feedback
player.world.spawnParticle(
Particle.HEART,
player.location.clone().add( 0.0, 2.0, 0.0 ),
3, 0.4, 0.2, 0.4, 0.0
)
player.playSound( player.location, Sound.ENTITY_GENERIC_DRINK, 0.5f, 0.4f )
player.sendActionBar(
player.trans(

View File

@@ -1,37 +0,0 @@
package club.mcscrims.speedhg.util
import org.bukkit.Location
import org.bukkit.Sound
import org.bukkit.entity.Player
object AbilityFeedback {
// ── Charge Feedback ────────────────────────────────────────────────────
fun playChargeReady( player: Player ) {
player.playSound( player.location, Sound.BLOCK_BEACON_POWER_SELECT, 1f, 1.6f )
}
fun playCharging( player: Player ) {
player.playSound( player.location, Sound.BLOCK_COMPARATOR_CLICK, 0.6f, 1.2f )
}
// ── Activation Feedback ────────────────────────────────────────────────
fun playActivation( player: Player ) {
player.playSound( player.location, Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 0.8f, 1.0f )
}
// ── Impact Feedback ───────────────────────────────────────────────────
fun playImpact( location: Location ) {
location.world?.playSound( location, Sound.BLOCK_ANVIL_LAND, 1f, 1.2f )
}
// ── Cooldown Feedback ──────────────────────────────────────────────────
fun playCooldownExpired( player: Player ) {
player.playSound( player.location, Sound.BLOCK_NOTE_BLOCK_PLING, 1f, 1.8f )
}
}

View File

@@ -1,50 +0,0 @@
package club.mcscrims.speedhg.util
import org.bukkit.Location
import org.bukkit.Particle
object AbilityParticles {
// ── Directional Impact Ring ────────────────────────────────────────────
fun spawnImpactRing( center: Location, radius: Double = 1.5 ) {
val particleCount = 12
for ( i in 0 until particleCount ) {
val angle = ( 2 * Math.PI * i / particleCount )
val x = kotlin.math.cos( angle ) * radius
val z = kotlin.math.sin( angle ) * radius
center.world?.spawnParticle(
Particle.FLAME,
center.clone().add( x, 0.5, z ),
1, 0.0, 0.0, 0.0, 0.0
)
}
}
// ── Charge Build Indicator ────────────────────────────────────────────
fun spawnChargeRing( center: Location, scale: Double ) {
val radius = 0.5 + ( scale * 1.5 )
center.world?.spawnParticle(
Particle.ELECTRIC_SPARK,
center,
8,
radius, radius, radius,
0.1
)
}
// ── Cooldown Indicator ────────────────────────────────────────────────
fun spawnCooldownIndicator( location: Location ) {
location.world?.spawnParticle(
Particle.FLAME,
location.clone().add( 0.0, 1.0, 0.0 ),
6,
0.3, 0.3, 0.3,
0.0
)
}
}

View File

@@ -5,6 +5,7 @@ import org.bukkit.Color
import org.bukkit.GameMode
import org.bukkit.Location
import org.bukkit.Particle
import org.bukkit.World
import org.bukkit.entity.Player
import org.bukkit.scheduler.BukkitRunnable
import org.bukkit.util.Vector
@@ -56,15 +57,46 @@ object AbilityUtils {
}.runTaskTimer( plugin, 0L, 1L )
}
fun drawParticleLine(
fun drawColoredParticleLine(
startLocation: Location,
endLocation: Location,
particle: Particle,
steps: Int,
dustColor: Color
) {
if ( steps <= 0 ) throw IllegalArgumentException( "Steps must be greater than 0." )
val world = startLocation.world ?: throw IllegalStateException( "World cannot be null." )
val options = Particle.DustOptions( dustColor, 1f )
spawnParticleLine(
startLocation,
endLocation, steps
) { ( x, y, z ) ->
world.spawnParticle( Particle.DUST, x, y, z, 1, 0.0, 0.0, 0.0, 0.0, options )
}
}
fun drawGenericParticleLine(
startLocation: Location,
endLocation: Location,
steps: Int,
particle: Particle
) {
val world = startLocation.world ?: throw IllegalStateException( "World cannot be null." )
spawnParticleLine(
startLocation,
endLocation, steps
) { ( x, y, z ) ->
world.spawnParticle( particle, x, y, z, 1, 0.0, 0.0, 0.0, 0.0 )
}
}
private fun spawnParticleLine(
startLocation: Location,
endLocation: Location,
steps: Int,
onParticle: (Triple<Double, Double, Double>) -> Unit
) {
if ( steps <= 0 ) throw IllegalArgumentException( "Steps must be greater than 0." )
if ( startLocation.world != endLocation.world ) throw IllegalStateException( "Locations must be in the same world." )
val diffX = ( endLocation.x - startLocation.x ) / steps
@@ -76,26 +108,8 @@ object AbilityUtils {
val x = startLocation.x + diffX * i
val y = startLocation.y + diffY * i
val z = startLocation.z + diffZ * i
world.spawnParticle( particle, x, y, z, 1, Particle.DustOptions( dustColor, 1f ))
onParticle(Triple( x, y, z ))
}
}
fun runForNearbyPlayers(
player: Player,
radius: Double,
filter: (Player) -> Boolean,
runnable: Consumer<in Player>
): MutableCollection<Player>
{
if ( radius <= 0.0 ) throw IllegalArgumentException( "Radius must be greater than 0.0." )
val world = player.world
val nearbyPlayers = world.getNearbyPlayers( player.location, radius ).filter( filter )
.filter { it != player && it.gameMode == GameMode.SURVIVAL }.toMutableList()
nearbyPlayers.forEach( runnable )
return nearbyPlayers
}
}