1.8.8 Can't make an arrow fly under a proper velocity

Discussion in 'Spigot Plugin Development' started by ZBLL, Jun 16, 2021.

  1. When I launch a projectile, I want it to fly to another player. This is my code:
    Code (Java):

    @EventHandler
    public void onShot(EntityDamageByEntityEvent e) {
        /** stuff */

            Vector v1 = ((Player) e.getEntity()).getEyeLocation().toVector();
            Vector v2 = shooter.getEyeLocation().toVector();
            Vector necessaryVelocity = shot.getVelocity();

            for (int i = 0; i < 10"); i++) {
                Arrow a = shooter.launchProjectile(Arrow.class);
                a.setVelocity(necessaryVelocity);
                a.setKnockbackStrength(2);
                a.setFireTicks(200);
                //arrows.add(a);
            }
        }
    }
    So from player 1 (v2) it must fly to player 2 (v1). I tried passing v1, v2 and necessaryVelocity in Arrow#setVelocity, but it only flies like half the way. Vector#multiply(2) also doesn't help.

    ZBLL
     
    #1 ZBLL, Jun 16, 2021
    Last edited: Jun 16, 2021
  2. Hey, you would need to get the velocity from the direction to the player from the arrow. You will get the vector by Location#toVector and subtract it from the arrow vector.
     
  3. Oh I am confused. So I get the victim's location, translate it to vector, then get the arrow's vector and substract the victim's vector from it? This doesn't make much sense though, since as I stated when I take the arrow's initial velocity, it only flies half the way, and substracting something from it just doesn't seem useful.

    ZBLL
     
    #3 ZBLL, Jun 16, 2021
    Last edited: Jun 16, 2021
  4. Sorry I just misunderstood you. You want that the entity always follows you and not just a one time push. You could archive that but with the same method. You would push the entity every few seconds to the player. This would have benefit that the position would be relative.

    And yes you would do entity location toVector than substract with the target location vector to push that to the target location. normalize would help to make it smooth and with multiply you could control the speed.
     
  5. Not exactly. Let's assume that there are 2 players standing still, not receiving knockback, though that's called hacking. And well, when one player successfully shoots another and, for example, a random number rolled is 11, then there are 10 (I'll likely reduce that) more arrows fired with the same velocity as the first one, therefore hitting the victim. I think I will also add a delay like 5 ticks between them, so they can at least hit a victim 1 out of 2 times. Oh and yeah, I will probably want to increase the vector by the slightest bit (1-ish block), so it can hit the player after he gets knocked back with the previous arrow. Well, using ((Arrow) e.getDamager()).getVelocity() doesn't work - it flies like half the way.

    ZBLL
     
  6. Pretty sure you can do something like this to make the projectile move from one location to another:

    Code (Java):
    Location projectileLoc = // get arrow location here
    Location targetLoc = // get target player loc

    Vector direction = projectileLoc.clone().subtract(targetLoc).toVector().normalize();

    // apply vector to projectile
     
    If you'd want to speed up the arrow you could just multiply the vector.
     
  7. Thanks, I'll test it tomorrow.
     
  8. I am using this code (totally not stolen from above):
    Code (Java):

    if (e.getDamager() instanceof Arrow && ((Arrow) e.getDamager()).getShooter() instanceof Player && e.getEntity() instanceof Player) {
        Arrow shot = (Arrow) e.getDamager();
        Player shooter = (Player) shot.getShooter();

        if (shooter.getItemInHand() == null) return; // The item in hand is not null.

        Enchantment ench = Enchantment.getById(UnderscoreEnchants.flamethrowerEnchantment.getId());

        if (!shooter.getItemInHand().getEnchantments().containsKey(ench)) return;

        Vector v1 = ((Player) e.getEntity()).getEyeLocation().toVector();
        Vector v2 = shooter.getEyeLocation().toVector();

        System.out.println("v1: " + v1.toString());
        System.out.println("v2: " + v2.toString());
        double distance = v1.distance(v2) - .5D;


        if (!(distance > UnderscoreEnchants.config.getDouble("FlamethrowerMinimumDistance"))) {
            return;
        }

        for (int i = 0; i < UnderscoreEnchants.config.getInt("FlamethrowerArrowsAmount"); i++) {
            Arrow a = shooter.launchProjectile(Arrow.class);
            Location projLoc = shot.getLocation();
            Location targetLoc = v2.toLocation(e.getEntity().getWorld());
            Vector dir = projLoc.clone().subtract(targetLoc).toVector().normalize();

            a.setVelocity(dir); // TODO
            a.setKnockbackStrength(2);
            a.setFireTicks(200);
        }
    }
     
    And this is what I get:
     
  9. Once the first arrow has hit the player, it triggers whatever event you're using. Next up you launch a new projectile with a velocity in the direction of the same player you've just hit.

    I don't know what you're exactly trying to accomplish, but if you want the second arrow to keep flying to the other player in a straight line you will either have to set the projectile gravity to false or reapply (and possibly recalculate if you want the arrow to go after the target) the velocity to the projectile.
     
  10. You saw me launching the first arrow? It hit the player. And I want to launch another arrow that will fly in the exact same direction (like the prev did) and hit the player respectively. I don't care if that happens in a straight line or it will loop-the-loop and do a barrel roll while flying - the point is it must fly to the point that the previous one has flown to. I don't see how I can do that, absolutely