Solved Help making projectile trails.

Discussion in 'Plugin Development' started by OkayName, May 12, 2021.

  1. Offline

    OkayName

    So Im making custom projectile trails for a server, and I came across a big issue: the arrows are too fast. I am currently using a SyncRepeatingTask to spawn particles at the location of the arrow after it has been shot, but the particle trail behind the arrow is not very frequent, and there are large, visible spaces between the particles. Here is the code I use to make the particle trail:
    Code:
    final int[] task = {0};
    task[0] = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, () -> {
        if (!e.getProjectile().isDead()) {
            e.getProjectile().getWorld().spawnParticle(Particle.VILLAGER_HAPPY, e.getProjectile().getLocation(), 1, 0.1, 0.1, 0.1, 1);
        } else {
            Bukkit.getScheduler().cancelTask(task[0]);
        }
    }, 0, 0);
    
    I was wondering if there is a way to make the particles appear more frequently. Thanks in advance!
     
  2. Offline

    KarimAKL

    @OkayName What if you create a custom arrow that overrides EntityArrow#tick() and spawns the particle?
     
  3. Offline

    davidclue

    @OkayName Do what @KarimAKL said or you can just get the arrows vector and spawn particles in front and behind the arrow to fill in those gaps, will look very weird on arrows that are fired slow though.
     
  4. Offline

    OkayName

    How would I go about doing that? Sorry if its a dumb question.
     
  5. Offline

    KarimAKL

    @OkayName Do not worry, NMS is not easy. :p
    Code:Java
    1. // Your custom arrow class
    2. public class CustomArrow extends EntityArrow {
    3.  
    4. public CustomArrow(Location location) {
    5. super(EntityTypes.ARROW, ((CraftWorld) location.getWorld()).getHandle());
    6. setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
    7. }
    8.  
    9. @Override
    10. public void tick() {
    11. super.tick();
    12.  
    13. // Spawn the particle
    14. }
    15. }
    16.  
    17. // Adding the entity to the world
    18. Location location = /* Your location */;
    19. CustomArrow arrow = new CustomArrow(location);
    20.  
    21. ((CraftWorld) location.getWorld()).getHandle().addEntity(arrow);

    Please let me know if you do not understand some parts of this. I will gladly explain. :)
     
  6. Offline

    OkayName

    Thank you, that helped me a lot, but there is one problem: When the arrow is spawned, it just falls and hits the ground. I looked into the class, but I couldnt find a function like setVector or setVelocity that I could use to make the arrow inherit the velocity of the arrow shot, which I could cancel later.
     
  7. Offline

    KarimAKL

    @OkayName You could make a new CraftArrow object using your new CustomArrow object to access the Bukkit API's methods.
    Example (open)
    Code:Java
    1. Location location = /* Your location */;
    2. CustomArrow arrow = new CustomArrow(location);
    3. CraftArrow craftArrow = new CraftArrow((CraftServer) Bukkit.getServer(), arrow);
    4.  
    5. craftArrow.setVelocity(new Vector(0, 0, 0));
    6.  
    7. ((CraftWorld) location.getWorld()).getHandle().addEntity(arrow);

    CraftBukkit source code (open)
    This is the source code for CraftEntity#setVelocity(Vector):
    Code:Java
    1. @Override
    2. public void setVelocity(Vector velocity) {
    3. Preconditions.checkArgument(velocity != null, "velocity");
    4. velocity.checkFinite();
    5. entity.setMot(CraftVector.toNMS(velocity));
    6. entity.velocityChanged = true;
    7. }
     
  8. Offline

    OkayName

    ok thank you

    Edit: I just tested out the code, and it seems as if the speed of the particles did not change. Im assuming its because I did not modify the tick speed at all, but I do not know how to do that.
     
    Last edited: May 13, 2021
  9. Offline

    KarimAKL

  10. Offline

    OkayName

    @KarimAKL I spawned the arrow through the CustomArrow class, and then I cancelled the original arrow that was shot.
     
  11. Offline

    KarimAKL

    @OkayName I mean, how did you spawn the particles? I believe particles have a speed attribute that you can set with commands in vanilla Minecraft.

    Edit: Yeah, I just checked here. It does indeed have a speed attribute.
     
  12. Offline

    OkayName

    @KarimAKL oh, I spawn it like this:
    Code:
    getWorld().getWorld().spawnParticle(Particle.VILLAGER_HAPPY, new Location(getWorld().getWorld(), locX(), locY(), locZ()), 1);
    
    but Im pretty sure the speed attribute isnt refferring to how often they spawn, but how clickly they travel once they've spawned. I'll try it out though, and see if it works.

    Edit: nope, it didnt work.
     
    Last edited: May 14, 2021
  13. Offline

    KarimAKL

    What do you mean by "how often they spawn?"
    Do you want to spawn multiple of them? Or do you want to spawn them every X ticks?
     
  14. Offline

    OkayName

    I want them to spawn every x milliseconds, not ticks, since ticks are too slow.
     
  15. Offline

    KarimAKL

    @OkayName The server only has up to 20 ticks a second, so that is impossible.

    1 tick is 50 milliseconds, so it is not too bad. Why do you want to spawn them faster?
     
  16. Offline

    OkayName

    Because the particles aren't frequent enough. When a player fires an arrow, it the particles are very spaced out, so it looks bad.
     
  17. Offline

    KarimAKL

    @OkayName Unfortunately, I believe that would require the client to spawn the particles since the server only allows up to said 20 ticks every second.
     
  18. Offline

    davidclue

    @OkayName Like I said before why not just spawn more particles behind the arrow every tick to fill the gaps.
     
    KarimAKL likes this.
  19. Offline

    OkayName

    alright I guess I will go with @davidclue method
     

Share This Page