91 lines
3.7 KiB
Java
91 lines
3.7 KiB
Java
package tc.oc.pgm.effect;
|
|
|
|
import org.bukkit.Color;
|
|
import org.bukkit.Particle;
|
|
import org.bukkit.entity.Arrow;
|
|
import org.bukkit.entity.Projectile;
|
|
import org.bukkit.event.EventHandler;
|
|
import org.bukkit.event.EventPriority;
|
|
import org.bukkit.event.Listener;
|
|
import org.bukkit.event.entity.ProjectileHitEvent;
|
|
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
|
import org.bukkit.metadata.FixedMetadataValue;
|
|
import tc.oc.pgm.PGM;
|
|
import tc.oc.pgm.events.ListenerScope;
|
|
import tc.oc.pgm.match.MatchModule;
|
|
import tc.oc.pgm.match.MatchScope;
|
|
import tc.oc.pgm.match.Repeatable;
|
|
import tc.oc.pgm.utils.EntityUtils;
|
|
|
|
/**
|
|
* Change the default projectile particle trails with a colored
|
|
* trail that matches the player's party color.
|
|
*/
|
|
@ListenerScope(MatchScope.RUNNING)
|
|
public class ProjectileTrailMatchModule extends MatchModule implements Listener {
|
|
|
|
private static final String TRAIL_META = "projectile_trail_color";
|
|
private static final String CRITICAL_META = "arrow_is_critical";
|
|
|
|
@Repeatable(scope = MatchScope.RUNNING)
|
|
public void tick() {
|
|
EntityUtils.entities(match.getWorld(), Projectile.class)
|
|
.filter(projectile -> projectile.hasMetadata(TRAIL_META))
|
|
.forEach(projectile -> {
|
|
if(projectile.isDead() || projectile.isOnGround()) {
|
|
projectile.removeMetadata(TRAIL_META, PGM.get());
|
|
} else {
|
|
final Color color = (Color) projectile.getMetadata(TRAIL_META, PGM.get()).value();
|
|
// Certain particles can have a specific color if:
|
|
// - Count is 0
|
|
// - Speed is 1
|
|
// - Delta vectors are RGB values from (0,1]
|
|
match.getWorld().spawnParticle(
|
|
Particle.REDSTONE,
|
|
projectile.getLocation(),
|
|
0,
|
|
rgbToParticle(color.getRed()),
|
|
rgbToParticle(color.getGreen()),
|
|
rgbToParticle(color.getBlue()),
|
|
1
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
private double rgbToParticle(int rgb) {
|
|
return Math.max(0.001, rgb / 255.0);
|
|
}
|
|
|
|
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
|
public void onProjectileLaunch(ProjectileLaunchEvent event) {
|
|
match.player(event.getActor()).ifPresent(shooter -> {
|
|
final Projectile projectile = event.getEntity();
|
|
projectile.setMetadata(TRAIL_META, new FixedMetadataValue(PGM.get(), shooter.getParty().getFullColor()));
|
|
// Set critical metadata to false in order to remove default particle trail.
|
|
// The metadata will be restored just before the arrow hits something.
|
|
if(projectile instanceof Arrow) {
|
|
final Arrow arrow = (Arrow) projectile;
|
|
arrow.setMetadata(CRITICAL_META, new FixedMetadataValue(PGM.get(), arrow.isCritical()));
|
|
arrow.setCritical(false);
|
|
}
|
|
});
|
|
}
|
|
|
|
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
|
public void onProjectileHit(ProjectileHitEvent event) {
|
|
match.player(event.getActor()).ifPresent(shooter -> {
|
|
final Projectile projectile = event.getEntity();
|
|
projectile.removeMetadata(TRAIL_META, PGM.get());
|
|
// Restore critical metadata to arrows if applicable
|
|
if(projectile instanceof Arrow) {
|
|
final Arrow arrow = (Arrow) projectile;
|
|
if(arrow.hasMetadata(CRITICAL_META)) {
|
|
arrow.setCritical(arrow.getMetadata(CRITICAL_META, PGM.get()).asBoolean());
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
}
|