ProjectAres/PGM/src/main/java/tc/oc/pgm/effect/ProjectileTrailMatchModule....

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());
}
}
});
}
}