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.AbilityResult
import club.mcscrims.speedhg.kit.ability.ActiveAbility import club.mcscrims.speedhg.kit.ability.ActiveAbility
import club.mcscrims.speedhg.kit.ability.PassiveAbility import club.mcscrims.speedhg.kit.ability.PassiveAbility
import club.mcscrims.speedhg.util.AbilityUtils
import club.mcscrims.speedhg.util.ItemBuilder import club.mcscrims.speedhg.util.ItemBuilder
import club.mcscrims.speedhg.util.trans import club.mcscrims.speedhg.util.trans
import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.Color
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.Particle import org.bukkit.Particle
import org.bukkit.Sound import org.bukkit.Sound
@@ -274,6 +276,11 @@ class PuppetKit : Kit()
enemies.forEach { enemy -> enemies.forEach { enemy ->
enemy.damage( capturedDrainDmg, player ) enemy.damage( capturedDrainDmg, player )
AbilityUtils.drawColoredParticleLine(
player.location,
enemy.location,
10, Color.RED
)
} }
val remainingHealBudget = capturedMaxTotalHeal - totalHealedHp val remainingHealBudget = capturedMaxTotalHeal - totalHealedHp
@@ -285,11 +292,6 @@ class PuppetKit : Kit()
totalHealedHp += actualHeal totalHealedHp += actualHeal
// Audio-visual feedback // 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.playSound( player.location, Sound.ENTITY_GENERIC_DRINK, 0.5f, 0.4f )
player.sendActionBar( player.sendActionBar(
player.trans( 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.GameMode
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.Particle import org.bukkit.Particle
import org.bukkit.World
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.scheduler.BukkitRunnable import org.bukkit.scheduler.BukkitRunnable
import org.bukkit.util.Vector import org.bukkit.util.Vector
@@ -56,15 +57,46 @@ object AbilityUtils {
}.runTaskTimer( plugin, 0L, 1L ) }.runTaskTimer( plugin, 0L, 1L )
} }
fun drawParticleLine( fun drawColoredParticleLine(
startLocation: Location, startLocation: Location,
endLocation: Location, endLocation: Location,
particle: Particle,
steps: Int, steps: Int,
dustColor: Color dustColor: Color
) { ) {
if ( steps <= 0 ) throw IllegalArgumentException( "Steps must be greater than 0." )
val world = startLocation.world ?: throw IllegalStateException( "World cannot be null." ) 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." ) if ( startLocation.world != endLocation.world ) throw IllegalStateException( "Locations must be in the same world." )
val diffX = ( endLocation.x - startLocation.x ) / steps val diffX = ( endLocation.x - startLocation.x ) / steps
@@ -76,26 +108,8 @@ object AbilityUtils {
val x = startLocation.x + diffX * i val x = startLocation.x + diffX * i
val y = startLocation.y + diffY * i val y = startLocation.y + diffY * i
val z = startLocation.z + diffZ * i val z = startLocation.z + diffZ * i
onParticle(Triple( x, y, z ))
world.spawnParticle( particle, x, y, z, 1, Particle.DustOptions( dustColor, 1f ))
} }
} }
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
}
} }