# How to get the closest player another player is directly looking at?

Discussion in 'Plugin Development' started by Janmm14, Nov 5, 2013.

Not open for further replies.
1. Offline

### Janmm14

Well my question is in the title. The range is 10 blocks.

I think you have to do some math with vectors, range checking, getting players of the current world. Just some notes. Please help me!

#1
2. Offline

### The_Doctor_123

Actually, Bukkit kindly created a method just for this kind of thing. In Player, there is a method called "getLineOfSight" and it returns a List of Blocks that the player is looking at, in order from closest to furthest. You can then iterate through the List until the Block is 1 meter(or whatever distance you'd like) from any Player.

#2
3. Offline

### blablubbabc

Get all the players in a cerain radius and then calculate the angle or dot product to each of them to get the nearest player the player is looking at.

I can give you the code for that when i am at home.

Edit: Okay, here you go:

Code:
```private Player getTarget(Player from) {
assert from != null;
// SOME FIXED VALUES (maybe define them globally somewhere):
double radius2 = 10.0D * 10.0D;
// the min. dot product (defines the min. angle to the target player)
// higher value means lower angle means that the player is looking "more directly" at the target):
// do some experiments, which angle / dotProduct value fits best for your case
double minDot = 0.98D;

String fromName = from.getName();
Location fromLocation = from.getEyeLocation();
String fromWorldName = fromLocation.getWorld().getName();
Vector fromDirection = fromLocation.getDirection().normalize();
Vector fromVectorPos = fromLocation.toVector();

Player target = null;
double minDistance2 = Double.MAX_VALUE;
for (Player somePlayer : Bukkit.getServer().getOnlinePlayers()) {
if (somePlayer.getName().equals(fromName)) continue;
Location newTargetLocation = somePlayer.getEyeLocation();
// check the world:
if (!newTargetLocation.getWorld().getName().equals(fromWorldName)) continue;
// check distance:
double newTargetDistance2 = newTargetLocation.distanceSquared(fromLocation);
// check angle to target:
Vector toTarget = newTargetLocation.toVector().subtract(fromVectorPos).normalize();
// check the dotProduct instead of the angle, because it's faster:
double dotProduct = toTarget.dot(fromDirection);
if (dotProduct > minDot && from.hasLineOfSight(somePlayer) && (target == null || newTargetDistance2 < minDistance2)) {
target = somePlayer;
minDistance2 = newTargetDistance2;
}
}

// can return null, if no player was found, which meets the conditions:
return target;
}
```
Edit2: Changed it to prioritize a smaller distance rather than a smaller angle for multiple potential targets.

Edit3: Fixed, to only check players in the same world.

#3
Janmm14 likes this.
4. Offline

#4