Get player in line of sight

Discussion in 'Plugin Development' started by RentAMonkey, May 9, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    RentAMonkey

    So I got this code:
    Code:
       
        @EventHandler
        public void onInteract(PlayerInteractEvent evt) {
        final Player p = evt.getPlayer();
        if(evt.getAction().equals(Action.RIGHT_CLICK_AIR))  {
            if(p.getItemInHand().getType() == Material.IRON_HOE) {
                if(main.playing.contains(p)) {
                    if(!shot.contains(p)) {
                        shot.add(p);
                        Block block1 = p.getTargetBlock(null, 1);
                        p.getWorld().playEffect(p.getLocation(), Effect.ZOMBIE_DESTROY_DOOR, 1);
                        p.getWorld().playEffect(p.getLocation(), Effect.ZOMBIE_CHEW_IRON_DOOR, 1);
                        p.getWorld().playEffect(block1.getLocation(), Effect.SMOKE, 1);
                        p.getWorld().playEffect(p.getEyeLocation(), Effect.SMOKE, 1);
                  Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() {
                        public void run() {
                            shot.remove(p);
                            }
                                }, 30L);
                    } else{
                        p.sendMessage(PREFIX + "§cYour weapon is reloading!");
                        }
                    }
                }
            }
        }
    }
    And I want to add code so if the player right clicks, the player in his crosshair will be killed.
    Can anybody help?
     
  2. Offline

    ZeusAllMighty11

    AFAIK it's not possible to check the player in crosshair. What I did, was:

    - Get line of sight for 100 blocks
    - Get all blocks that are in the sight (not the ones around it)
    - Get all locations of the blocks, and check for nearby entities
    - If entity is a player, get the player
    - Do something (kill )
     
  3. Offline

    RentAMonkey

  4. Offline

    caseif

    At the risk of making an off-topic post, I'd just like to say that your avatar is hilariously appropriate for this thread.
     
  5. Offline

    RentAMonkey

    Just realised :D

    But seriously can anybody help me with My Problem?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 1, 2016
  6. Offline

    Comphenix

    It is - just use getEyeLocation() and getDirection() on the player, and you can extract the approximate direction their looking in and thus the location of the crosshair.

    In fact, by reworking my allow invisible/hidden players to be attacked example, I made a simple but accurate method for detecting a right-click on players over long distances (download):
    Code:java
    1. public class ExampleMod extends JavaPlugin implements Listener {
    2. final int ATTACK_REACH = 100; // meters
    3.  
    4. @Override
    5. public void onEnable() {
    6. getServer().getPluginManager().registerEvents(this, this);
    7. }
    8.  
    9. @EventHandler
    10. public void onInteract(PlayerInteractEvent evt) {
    11. final Player observer = evt.getPlayer();
    12.  
    13. if(evt.getAction().equals(Action.RIGHT_CLICK_AIR)) {
    14. if(observer.getItemInHand().getType() == Material.IRON_HOE) {
    15.  
    16. Location observerPos = observer.getEyeLocation();
    17. Vector3D observerDir = new Vector3D(observerPos.getDirection());
    18.  
    19. Vector3D observerStart = new Vector3D(observerPos);
    20. Vector3D observerEnd = observerStart.add(observerDir.multiply(ATTACK_REACH));
    21.  
    22. Player hit = null;
    23.  
    24. // Get nearby entities
    25. for (Player target : observer.getWorld().getPlayers()) {
    26. // Bounding box of the given player
    27. Vector3D targetPos = new Vector3D(target.getLocation());
    28. Vector3D minimum = targetPos.add(-0.5, 0, -0.5);
    29. Vector3D maximum = targetPos.add(0.5, 1.67, 0.5);
    30.  
    31. if (target != observer && hasIntersection(observerStart, observerEnd, minimum, maximum)) {
    32. if (hit == null ||
    33. hit.getLocation().distanceSquared(observerPos) >
    34. target.getLocation().distanceSquared(observerPos)) {
    35.  
    36. hit = target;
    37. }
    38. }
    39. }
    40.  
    41. // Hit the closest player
    42. if (hit != null) {
    43. hit.damage(5, observer);
    44. }
    45. }
    46. }
    47. }
    48.  
    49. // Source:
    50. // [url]http://www.gamedev.net/topic/338987-aabb---line-segment-intersection-test/[/url]
    51. private boolean hasIntersection(Vector3D p1, Vector3D p2, Vector3D min, Vector3D max) {
    52. final double epsilon = 0.0001f;
    53.  
    54. Vector3D d = p2.subtract(p1).multiply(0.5);
    55. Vector3D e = max.subtract(min).multiply(0.5);
    56. Vector3D c = p1.add(d).subtract(min.add(max).multiply(0.5));
    57. Vector3D ad = d.abs();
    58.  
    59. if (Math.abs(c.x) > e.x + ad.x)
    60. return false;
    61. if (Math.abs(c.y) > e.y + ad.y)
    62. return false;
    63. if (Math.abs(c.z) > e.z + ad.z)
    64. return false;
    65.  
    66. if (Math.abs(d.y * c.z - d.z * c.y) > e.y * ad.z + e.z * ad.y + epsilon)
    67. return false;
    68. if (Math.abs(d.z * c.x - d.x * c.z) > e.z * ad.x + e.x * ad.z + epsilon)
    69. return false;
    70. if (Math.abs(d.x * c.y - d.y * c.x) > e.x * ad.y + e.y * ad.x + epsilon)
    71. return false;
    72.  
    73. return true;
    74. }
    75. }

    You also need to add the following class to your project:
    Code:java
    1.  
    2. package com.comphenix.example;
    3.  
    4. /*
    5. * Attack hidden players
    6. *
    7. * Copyright 2012 Kristian S. Stangeland (Comphenix)
    8. *
    9. * This library is free software; you can redistribute it and/or
    10. * modify it under the terms of the GNU Lesser General Public
    11. * License as published by the Free Software Foundation; either
    12. * version 2.1 of the License, or (at your option) any later version.
    13. *
    14. * This library is distributed in the hope that it will be useful,
    15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
    16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    17. * Lesser General Public License for more details.
    18. *
    19. * You should have received a copy of the GNU Lesser General Public
    20. * License along with this library. If not, see <[url]http://www.gnu.org/licenses/>[/url].
    21. */
    22.  
    23. import org.bukkit.Location;
    24. import org.bukkit.util.Vector;
    25.  
    26. public class Vector3D {
    27. /**
    28.   * Represents the null (0, 0, 0) origin.
    29.   */
    30. public static final Vector3D ORIGIN = new Vector3D(0, 0, 0);
    31.  
    32. // Use protected members, like Bukkit
    33. public final double x;
    34. public final double y;
    35. public final double z;
    36.  
    37. /**
    38.   * Construct an immutable 3D vector.
    39.   */
    40. public Vector3D(double x, double y, double z) {
    41. this.x = x;
    42. this.y = y;
    43. this.z = z;
    44. }
    45.  
    46. /**
    47.   * Construct an immutable floating point 3D vector from a location object.
    48.   * @param location - the location to copy.
    49.   */
    50. public Vector3D(Location location) {
    51. this(location.toVector());
    52. }
    53.  
    54. /**
    55.   * Construct an immutable floating point 3D vector from a mutable Bukkit vector.
    56.   * @param vector - the mutable real Bukkit vector to copy.
    57.   */
    58. public Vector3D(Vector vector) {
    59. if (vector == null)
    60. throw new IllegalArgumentException("Vector cannot be NULL.");
    61. this.x = vector.getX();
    62. this.y = vector.getY();
    63. this.z = vector.getZ();
    64. }
    65.  
    66. /**
    67.   * Convert this instance to an equivalent real 3D vector.
    68.   * @return Real 3D vector.
    69.   */
    70. public Vector toVector() {
    71. return new Vector(x, y, z);
    72. }
    73.  
    74. /**
    75.   * Adds the current vector and a given position vector, producing a result vector.
    76.   * @param other - the other vector.
    77.   * @return The new result vector.
    78.   */
    79. public Vector3D add(Vector3D other) {
    80. if (other == null)
    81. throw new IllegalArgumentException("other cannot be NULL");
    82. return new Vector3D(x + other.x, y + other.y, z + other.z);
    83. }
    84.  
    85. /**
    86.   * Adds the current vector and a given vector together, producing a result vector.
    87.   * @param other - the other vector.
    88.   * @return The new result vector.
    89.   */
    90. public Vector3D add(double x, double y, double z) {
    91. return new Vector3D(this.x + x, this.y + y, this.z + z);
    92. }
    93.  
    94. /**
    95.   * Substracts the current vector and a given vector, producing a result position.
    96.   * @param other - the other position.
    97.   * @return The new result position.
    98.   */
    99. public Vector3D subtract(Vector3D other) {
    100. if (other == null)
    101. throw new IllegalArgumentException("other cannot be NULL");
    102. return new Vector3D(x - other.x, y - other.y, z - other.z);
    103. }
    104.  
    105. /**
    106.   * Substracts the current vector and a given vector together, producing a result vector.
    107.   * @param other - the other vector.
    108.   * @return The new result vector.
    109.   */
    110. public Vector3D subtract(double x, double y, double z) {
    111. return new Vector3D(this.x - x, this.y - y, this.z - z);
    112. }
    113.  
    114. /**
    115.   * Multiply each dimension in the current vector by the given factor.
    116.   * @param factor - multiplier.
    117.   * @return The new result.
    118.   */
    119. public Vector3D multiply(int factor) {
    120. return new Vector3D(x * factor, y * factor, z * factor);
    121. }
    122.  
    123. /**
    124.   * Multiply each dimension in the current vector by the given factor.
    125.   * @param factor - multiplier.
    126.   * @return The new result.
    127.   */
    128. public Vector3D multiply(double factor) {
    129. return new Vector3D(x * factor, y * factor, z * factor);
    130. }
    131.  
    132. /**
    133.   * Divide each dimension in the current vector by the given divisor.
    134.   * @param divisor - the divisor.
    135.   * @return The new result.
    136.   */
    137. public Vector3D divide(int divisor) {
    138. if (divisor == 0)
    139. throw new IllegalArgumentException("Cannot divide by null.");
    140. return new Vector3D(x / divisor, y / divisor, z / divisor);
    141. }
    142.  
    143. /**
    144.   * Divide each dimension in the current vector by the given divisor.
    145.   * @param divisor - the divisor.
    146.   * @return The new result.
    147.   */
    148. public Vector3D divide(double divisor) {
    149. if (divisor == 0)
    150. throw new IllegalArgumentException("Cannot divide by null.");
    151. return new Vector3D(x / divisor, y / divisor, z / divisor);
    152. }
    153.  
    154. /**
    155.   * Retrieve the absolute value of this vector.
    156.   * @return The new result.
    157.   */
    158. public Vector3D abs() {
    159. return new Vector3D(Math.abs(x), Math.abs(y), Math.abs(z));
    160. }
    161.  
    162. @Override
    163. public String toString() {
    164. return String.format("[x: %s, y: %s, z: %s]", x, y, z);
    165. }
    166. }

    This works suprisingly well. Though, it doesn't take into account physical barriers such as blocks. But that's fairly simple to implement with Player.getLineOfSight.
     
  7. Offline

    RentAMonkey

    Thank you so much, this code works very well!
     
    Comphenix likes this.
  8. Thank you for sharing.
     
  9. Offline

    nitrousspark

    Code:
     
     
    public static boolean isPlayerLookingAtHitBox(Player p1, Location loc, int width, int height)
    {
    boolean isLooking = false;
    Location loc1 = lookAt(p1.getLocation(), loc);
    Location loc2 = p1.getLocation();
    int yaw1 = (int)Math.abs(loc1.getYaw());
    int yaw2 = (int)Math.abs(loc2.getYaw());
    int pitch1 = (int)Math.abs(loc1.getPitch());
    int pitch2 = (int)Math.abs(loc2.getPitch());
    if(yaw1 + width > yaw2 || yaw1 - width < yaw2 && pitch1 + height > pitch2 || pitch1 - height < pitch2)
    {
    isLooking = true;
    }
    return isLooking;
    }
     
     
    public static Location lookAt(Location loc, Location lookat)
    {
     
    loc = loc.clone();
     
    double dx = lookat.getX() - loc.getX();
    double dy = lookat.getY() - loc.getY();
    double dz = lookat.getZ() - loc.getZ();
     
    if(dx != 0)
    {
    if(dx < 0)
    {
    loc.setYaw((float)(1.5 * Math.PI));
    }
    else
    {
    loc.setYaw((float)(0.5 * Math.PI));
    }
    loc.setYaw((float)loc.getYaw() - (float)Math.atan(dz / dx));
    }
    else if(dz < 0)
    {
    loc.setYaw((float)Math.PI);
    }
     
    double dxz = Math.sqrt(Math.pow(dx, 2) + Math.pow(dz, 2));
     
    loc.setPitch((float)-Math.atan(dy / dxz));
     
    loc.setYaw(-loc.getYaw() * 180f / (float)Math.PI);
    loc.setPitch(loc.getPitch() * 180f / (float)Math.PI);
     
    return loc;
    }
    
    where loc is the location of the hitbox
     
Thread Status:
Not open for further replies.

Share This Page