Solved Adjust yaw angle for right-hand particle beam

Discussion in 'Spigot Plugin Development' started by ZizzyZizzy, Feb 15, 2020.

1. ZizzyZizzy

Having a little trouble with the math on this one.

After finding a couple of helpful posts here, I've successfully created a sine wave particle beam emanating from the player's right hand. The problem is the yaw needs to be adjusted so the target matches the player's reticle. Right now the target is off to the right slightly.

Here's what I have so far:

Code (Text):
public static void beamTest2(Player p){
Location eyeLoc = p.getEyeLocation();
World world = eyeLoc.getWorld();
final Vector eyeDir = p.getLocation().getDirection().normalize().multiply(1);
Location rightHandLoc = getRightHandLocation(p);
int beamLength = 40;
double points = 20;
double radius = .5;
double increment = (2 * Math.PI) / points;
for(int duration = 0; duration < beamLength; duration++) {
double angle = duration * increment;
double y = radius * Math.sin(angle);

world.spawnParticle(Particle.FLAME,rightHandLoc.getX(),rightHandLoc.getY() + y, rightHandLoc.getZ(), 0);
}
}

..and the function to calculate the right hand position (thanks @JacobCrofts in this post):

Code (Text):
public static Location getRightHandLocation(Player player){
double yawRightHandDirection = Math.toRadians(-1 * player.getEyeLocation().getYaw() - 45);
double x = 0.45 * Math.sin(yawRightHandDirection) + player.getLocation().getX();
double y = player.getEyeLocation().getY() - 0.6;
double z = 0.45 * Math.cos(yawRightHandDirection) + player.getLocation().getZ();
return new Location(player.getWorld(), x, y, z);
}
I've tried a couple of things using vector differences to calculate the new yaw, but none of them are working for me. Still trying to wrap my head around the math for stuff like this.

2. Schottky

Here's something I use:
Code (Text):
protected void transformToHandLocation(Location location, @NotNull final Player player, final double itemLength, final boolean mainHand) {
final double handOffset = mainHand ? -0.5 : 0.5;
final double yaw = Math.toRadians(player.getLocation().getYaw());
// applies the rotation
final double x = handOffset * Math.cos(yaw) - itemLength * Math.sin(yaw);
final double z = handOffset * Math.sin(yaw) + itemLength * Math.cos(yaw);
}
But can you specify a little more what your problem is? As far as I understood, you can spawn the sin-wave but it's a little offset?

3. ZizzyZizzy

The sine wave spawns perfectly with the source appearing to be the right hand. It's the particle/target direction I'm having problems adjusting.

I want the target direction to be the same as the player target reticle. Right now the target is also offset to the right of the player's reticle.

4. Schottky

oooh, well you are adjusting the location to be at the player's hand. If you use my method, simply set the handOffset to 0 (and maybe do some other tweaking). Using JacobCroft's method I would suppose to multiply x and z by 1 and not 0.45

5. ZizzyZizzy

Nope, that just changes the offset in relation to the center of the player. The target still has the wrong yaw. I just can't figure out how to recalculate the yaw so the "aim" of the hand particle matches the players eye "aim".

I tried converting the yaw to radians, subtracting a small amount, and then using setYaw, but that didn't do anything for any values I subtracted.

Another use of this would be to add subtle, random adjustments to the projectile so it doesn't always go exactly to the player's target reticle. This would be great for RPG plugins where your experience determines your accuracy, for instance.

6. finnbon

You need to change eyeDir. Currently it's just the direction a player looks in, but that won't suffice since you change the point of origin. You must find the location at which the wave will stop (the location the player is looking at) and calculate the vector between the player's hand and that target location.

7. ZizzyZizzy

@finnbon I was so close! Thanks, that should have come to me sooner.

Here is the fixed code for anyone else frustrated with what should be simple:

Code (Text):

Location rightHandLoc =  getRightHandLocation(p);
final Vector eyeDir = eyeLoc.getDirection().normalize();

// Calculate the new correct dir vector for the beam so it hits where the player is looking
// Since the beam length is 40 and each particle moves 0.5 blocks, we need a location 20 blocks away
Location targetLoc = eyeLoc.add(eyeDir.multiply(20));
// Calculate the vector between the right hand and target location
Vector newDir = targetLoc.clone().subtract(rightHandLoc).toVector().normalize();

and further down we use this newDir instead of eyeDir:

Code (Text):

https://ibb.co/yppj55F

File size:
200.1 KB
Views:
20
8. finnbon

Great to hear you fixed it! I see one issue with your current approach however.

I assume this beam of yours is going to be hitting something, which means that it could potentially run into a wall or an entity. When you use a set distance of 20 blocks, when aiming at a mob that is 5 blocks away from you, the beam won't fly at that mob. I assume that, when your target is closer than 20 blocks to you, you'd want to aim for that target or wall instead of just a set 20 blocks away from your view. To fix this, you'd have to find any entity your player is looking at, or find if there's a block obstructing the player's view. If so, then use that location as your target.

9. ZizzyZizzy

Yup, that was actually intended for what I was working on. It's a slow moving, snake-wave of destruction. Sine wave flames from both hands, with lava straight down the middle. Eventually the right and left flame particle waves converge and there will be a fiery explosion.

POC WIP:
https://ibb.co/TY79Qj9