added Homing Arrows and trajectory visualization

This commit is contained in:
newt_00 2025-03-06 18:46:16 -05:00
parent 3a4e07fee3
commit 45e0cacd2e
52 changed files with 212 additions and 1 deletions

Binary file not shown.

Binary file not shown.

View File

@ -157,6 +157,15 @@ shop:
display_name: "Mace Of Storms"
available: true
tool_id: 7
utils7:
items:
tracerbow:
material: KOWLEDGE_BOOK
price: 54000
quantity: 1
display_name: "Tracer Bow"
available: true
tool_id: 8
poor: "you're too poor for that, get gooder..."
inventory_full: "you got too much clutter, cant fit your purchase into that mess..."
pagination:

View File

@ -0,0 +1,106 @@
package CoswayUtil;
import org.bukkit.*;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityShootBowEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class BowTrajectoryVisualizer implements Listener {
private final CoswayUtil plugin;
private final Map<Player, BukkitRunnable> activeTrajectories = new HashMap<>();
public BowTrajectoryVisualizer(CoswayUtil plugin) {
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onPlayerDrawBow(PlayerInteractEvent event) {
Player player = event.getPlayer();
if(Objects.equals(getpdc(player,"bow_trail"),"true")) {
ItemStack item = player.getInventory().getItemInMainHand();
// Ensure the player is holding a bow
if (item.getType().toString().contains("BOW") && event.getAction().toString().contains("RIGHT_CLICK")) {
startTrajectory(player);
}
}
}
@EventHandler
public void onArrowShoot(EntityShootBowEvent event) {
if (event.getEntity() instanceof Player player) {
if(Objects.equals(getpdc(player,"bow_trail"),"true")) {
stopTrajectory(player);
}
}
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
if(event instanceof Player player) {
if (Objects.equals(getpdc(player, "bow_trail"), "true")) {
stopTrajectory(event.getPlayer());
}
}
}
private void startTrajectory(Player player) {
stopTrajectory(player); // Ensure only one trajectory is active
BukkitRunnable task = new BukkitRunnable() {
@Override
public void run() {
if (!player.isOnline() || !player.isHandRaised()) {
stopTrajectory(player);
return;
}
Location eyeLocation = player.getEyeLocation();
Vector direction = eyeLocation.getDirection().normalize().multiply(3.5); // Max bow power velocity
Location particleLocation = eyeLocation.clone();
double velX = direction.getX();
double velY = direction.getY();
double velZ = direction.getZ();
for (int i = 0; i < 100; i++) { // Simulating up to ~5 seconds of flight
particleLocation.add(velX, velY, velZ);
player.getWorld().spawnParticle(Particle.DUST, particleLocation, 1, 0, 0, 0, 0, new Particle.DustOptions(Color.ORANGE, 1));
velY -= 0.08; // Corrected gravity application
velX *= 0.99; // Air resistance
velY *= 0.99;
velZ *= 0.99;
}
}
};
task.runTaskTimer(plugin, 0L, 2L);
activeTrajectories.put(player, task);
}
public String getpdc(Player player, String key) {
NamespacedKey thiskey = new NamespacedKey(plugin, key);
String value = player.getPersistentDataContainer().get(thiskey, PersistentDataType.STRING);
return value;
}
private void stopTrajectory(Player player) {
if (activeTrajectories.containsKey(player)) {
activeTrajectories.get(player).cancel();
activeTrajectories.remove(player);
}
}
}

View File

@ -89,6 +89,10 @@ public final class CoswayUtil extends JavaPlugin implements Listener {
// Register TotemShield
new TotemShield(this);
registration("Totem Shield",3);
// register bow trejectory visualizer
new BowTrajectoryVisualizer(this);
getServer().getPluginManager().registerEvents(new BowTrajectoryVisualizer(this), this);
registration("Bow Trajectory Vistualizer",3);
// Register the ShadowStep listener
new MobLevitationWand(this);
registration("Levitation Wand",2);
@ -131,6 +135,9 @@ public final class CoswayUtil extends JavaPlugin implements Listener {
NoteStudio.init(this);
registration("Note Studio",1);
new TreasureFountain(this);
new TracerArrowListener(this);
getServer().getPluginManager().registerEvents(new TracerArrowListener(this), this);
registration("Tracer Arrows",3);
getServer().getPluginManager().registerEvents(new TreasureFountain(this), this);
registration("Treasure Fountain (W.I.P.)",3);
new BankingSystem(this,economy);
@ -182,6 +189,9 @@ public final class CoswayUtil extends JavaPlugin implements Listener {
if(removeCustomKnowledgeBook(player,ChatColor.GREEN+"Illumination Wand")) {
player.getInventory().addItem(IlluminationWand.getIlluminationWand());
}
if(removeCustomKnowledgeBook(player,ChatColor.GREEN+"Tracer Bow")) {
player.getInventory().addItem(TracerArrowListener.getTracer());
}
}
}
}.runTaskTimer(this,0,2);

View File

@ -0,0 +1,77 @@
package CoswayUtil;
import org.bukkit.*;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import java.util.Comparator;
import java.util.List;
public class TracerArrowListener implements Listener {
private final CoswayUtil plugin;
public TracerArrowListener(CoswayUtil plugin) {
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onArrowShoot(ProjectileLaunchEvent event) {
if (!(event.getEntity() instanceof Arrow arrow)) return;
if (!(arrow.getShooter() instanceof Player player)) return;
if (!player.getInventory().getItemInMainHand().containsEnchantment(Enchantment.LOYALTY)) return;
new BukkitRunnable() {
@Override
public void run() {
if (arrow.isDead() || arrow.isInBlock()) {
cancel();
return;
}
LivingEntity target = getNearestEntity(arrow);
if (target == null) return;
// Adjust trajectory to aim at target
Vector newVelocity = target.getLocation().toVector().subtract(arrow.getLocation().toVector()).normalize().multiply(3.0);
arrow.setVelocity(newVelocity);
// Visual and sound feedback
arrow.getWorld().spawnParticle(Particle.DUST, arrow.getLocation(), 5, 0.1, 0.1, 0.1, 0, new Particle.DustOptions(Color.ORANGE, 1));
arrow.getWorld().playSound(arrow.getLocation(), Sound.ENTITY_ARROW_HIT_PLAYER, 0.5f, 1.5f);
}
}.runTaskTimer(plugin, 5L, 2L); // Starts after 5 ticks, updates every 2 ticks
}
public static ItemStack getTracer() {
ItemStack wand = new ItemStack(Material.BOW);
ItemMeta meta = wand.getItemMeta();
if (meta != null) {
meta.setDisplayName(ChatColor.YELLOW + "Tracer Bow");
meta.setLore(java.util.Arrays.asList(ChatColor.GOLD + "Automatically home on hostiles", ChatColor.GRAY + "Homing Range: 25 blocks"));
meta.setUnbreakable(true);
meta.addEnchant(Enchantment.LOYALTY,1,true);
meta.setEnchantable(10);
wand.setItemMeta(meta);
}
return wand;
}
private LivingEntity getNearestEntity(Arrow arrow) {
List<Entity> entities = arrow.getNearbyEntities(25, 25, 25);
return entities.stream()
.filter(e -> e instanceof LivingEntity && !(e instanceof Player) && (e instanceof Monster))
.map(e -> (LivingEntity) e)
.min(Comparator.comparingDouble(e -> e.getLocation().distanceSquared(arrow.getLocation())))
.orElse(null);
}
}

View File

@ -157,6 +157,15 @@ shop:
display_name: "Mace Of Storms"
available: true
tool_id: 7
utils7:
items:
tracerbow:
material: KOWLEDGE_BOOK
price: 54000
quantity: 1
display_name: "Tracer Bow"
available: true
tool_id: 8
poor: "you're too poor for that, get gooder..."
inventory_full: "you got too much clutter, cant fit your purchase into that mess..."
pagination: