Determine whether the player can see a mob

Discussion in 'Plugin Development' started by Codex Arcanum, Jan 22, 2012.

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

    Codex Arcanum

    Is there any easy way to detect if the player is looking in the direction of a mob, then freeze the mob if they are? For anyone who cares, I want to recreate the weeping angels mod (using existing mobs), but for bukkit.
     
  2. Offline

    AbeJ

    I would love to know this as well. You can use canSeeEntity, but that relies on CB methods (I don't think there's a Bukkit function for it).
     
  3. Offline

    bergerkiller

    I've seen this question get posted quite often. Guess it's time to write a solution for this in the Resources area. :)
     
    Codex Arcanum likes this.
  4. Offline

    tkausl

    Take a look in the Enderman-Classes.
     
  5. Offline

    AbeJ

    You're the most helpful person on these forums I know.
     
  6. Offline

    bergerkiller

    I've got only one issue: the player cna change their field of view (FoV) in the settings. What do you define as 'entity x can see entity z'? Right now I'm using tracing like the block tracer does.

    EDIT

    First bit of code:
    Code:
        public static Block getTarget(Location from, int distance, byte... transparentTypeIds) {
            if (transparentTypeIds.length == 0) {
                return getTarget(from, distance, (Set<Byte>) null);
            } else {
                Set<Byte> types = new HashSet<Byte>(transparentTypeIds.length);
                for (byte b : transparentTypeIds) types.add(b);
                return getTarget(from, distance, types);
            }
        }
        public static Block getTarget(Location from, int distance, Set<Byte> transparentTypeIds) {
            BlockIterator itr = new BlockIterator(from, 0, distance);
            while (itr.hasNext()) {
                Block block = itr.next();
                int id = block.getTypeId();
                if (transparentTypeIds == null) {
                    if (id == 0) continue;
                } else if (transparentTypeIds.contains((byte) id)) {
                    continue;
                }
                return block;
            }
            return null;
        }
    This is pretty much done:
    Code:
        public static Block getTarget(Location from, int distance, byte... transparentTypeIds) {
            if (transparentTypeIds.length == 0) {
                return getTarget(from, distance, (Set<Byte>) null);
            } else {
                Set<Byte> types = new HashSet<Byte>(transparentTypeIds.length);
                for (byte b : transparentTypeIds) types.add(b);
                return getTarget(from, distance, types);
            }
        }
        public static Block getTarget(Location from, int distance, Set<Byte> transparentTypeIds) {
            BlockIterator itr = new BlockIterator(from, 0, distance);
            while (itr.hasNext()) {
                Block block = itr.next();
                int id = block.getTypeId();
                if (transparentTypeIds == null) {
                    if (id == 0) continue;
                } else if (transparentTypeIds.contains((byte) id)) {
                    continue;
                }
                return block;
            }
            return null;
        }
        public static Block getTarget(LivingEntity from, int distance, Set<Byte> transparentTypeIds) {
            return getTarget(from.getEyeLocation(), distance, transparentTypeIds);
        }
        public static Block getTarget(LivingEntity from, int distance, byte... transparentTypeIds) {
            return getTarget(from.getEyeLocation(), distance, transparentTypeIds);
        }
        public static boolean canSee(LivingEntity from, Location to, Set<Byte> transparentTypeIds) {
            return getTarget(from, (int) Math.ceil(from.getLocation().distance(to)), transparentTypeIds) == null;
        }
        public static boolean canSee(LivingEntity from, Location to, byte... transparentTypeIds) {
            return getTarget(from, (int) Math.ceil(from.getLocation().distance(to)), transparentTypeIds) == null;
        }
    canSee will return if the entity can see a certain location, but doesn't take the entities' looking-at in mind.

    It basically checks if the entity CAN see a certain location, it does not check if it DOES see a certain location. I need to know a certain field of view angle for that.

    Code:
    if (canSee(entity, target, 0, 11, 12)) {
        //can see           
    }
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 23, 2016
  7. Offline

    Codex Arcanum

    Was not expecting that thorough of a response :). I actually think that I may try using a method that uses the lookat function you wrote, then checks how much the horizontal rotation (that's yaw right?) changed from he original, since I don't really to worry about intervening blocks. If that doesn't work I'll try the above. Thanks so much for the help :).
     
  8. Offline

    bergerkiller

    Codex Arcanum the above deals with blocks in between the player and the object to see. A player obviously can't see the players behind a wall, so you need to add checks against that. And yup, you need to calculate the look-at angle and compare this to the player yaw. Then, based on the distance, figure out a nice function that returns true or false.
     
Thread Status:
Not open for further replies.

Share This Page