How can I check if a player can visually see another?

Discussion in 'Plugin Development' started by caldabeast, Jun 15, 2012.

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

    caldabeast

    For the plugin im coding, I need to be able to check if a certain player can see the entity for another. I tried p.canSee(other), but then I found that it doesn't do what I had hoped, and instead worked with player invisibility. Does anyone have any method to accomplish this? I would greatly appreciate it!
     
  2. Offline

    r0306

    caldabeast
    If the players aren't invisible to one another, they they technically should be able to see each other. What exactly are you trying to do here? Do you mean field of view?
     
  3. Offline

    CorrieKay

    he means FoV
     
  4. Offline

    r0306

    caldabeast
    CorrieKay
    In that case, you could do something like this:
    Code:
    double view = (double) Bukkit.getServer().getViewDistance() * 16;
    List<Entity> nearby = player.getLocation().getNearbyEntities(view, view, view);
     
  5. Offline

    caldabeast

    that would get players behind you as well. I need some method that only receives entities within line of sight of the player.
    Any ideas? CorrieKay
     
  6. Offline

    r0306

    caldabeast
    You would do that by getting the player's direction but even then, they could just use F5 to look behind them so it's pretty much pointless to do so.
     
  7. Offline

    CorrieKay

    there are two different things when regarding vision, and i think FatherOfTime put it, that its focus, and FoV

    focus is what youre looking directly at, and its fairly easy to do..

    However, FoV is not. Im not sure how to go about doing that :\
     
  8. Offline

    caldabeast

    What im trying to accomplish moreso is an AOE attack for players withing five blocks of your target, but only if you can actually see them (by which them being infront of you). How could I get the facing direction of a player? p.getDirection() doesn't exist.

    Darn.
    Going to a similar issue from this, would there be any way to get the cardinal direction that a person is facing?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 26, 2016
  9. Offline

    r0306

    The method getDirection() is a member of the Location class so you need to get the player's location before getting their direction.
    Code:
    p.getLocation().getDirection();
     
  10. Offline

    caldabeast

    Vectors... I suppose I learn how to actually use those. Are there any good tutorials on the subject?
     
  11. Offline

    CorrieKay

    i was just looking that up, and the only thing i saw was getVelocity, which returns a vector, but ive never worked with vectors.. (i may be wrong, but i think the vector is how much change per tick there is to each coordinate)

    It would take a bit of work, but i think thats the best place to look. (though i dont know if it would give you pitch of view... :\)
     
  12. Offline

    caldabeast

    Well thanks for your help anyway!
     
  13. Offline

    r0306

  14. Offline

    Technius

    I think you need a bit of trig here...
     
  15. Can't the FoV be changed by the client (at least a bit)?
    However, what I would do is use getNearbyEntities just like r0306 did.
    Then, you probably need some math.
    Code:
    /**
        * Gets entities inside a cone.
        * @see Utilities#getPlayersInCone(List, Location, int, int, int)
        *
        * @param entities - {@code List<Entity>}, list of nearby entities
        * @param startpoint - {@code Location}, center point
        * @param radius - {@code int}, radius of the circle
        * @param degrees - {@code int}, angle of the cone
        * @param direction - {@code int}, direction of the cone
        * @return {@code List<Entity>} - entities in the cone
        */
        public static List<Entity> getEntitiesInCone(List<Entity> entities, Location startpoint, int radius, int degrees, int direction)
        {
            List<Entity> newEntities = new ArrayList<Entity>();
         
            int[] startPos = new int[] { (int)startpoint.getX(), (int)startpoint.getZ() };
         
            int[] endA = new int[] { (int)(radius * Math.cos(direction - (degrees / 2))), (int)(radius * Math.sin(direction - (degrees / 2))) };
       
            for(Entity e : entities)
            {
                Location l = e.getLocation();       
                int[] entityVector = getVectorForPoints(startPos[0], startPos[1], l.getBlockX(), l.getBlockY());
     
                double angle = getAngleBetweenVectors(endA, entityVector);
                if(Math.toDegrees(angle) < degrees && Math.toDegrees(angle) > 0)
                    newEntities.add(e);
            }
            return newEntities;
        }
        /**
        * Created an integer vector in 2d between two points
        *
        * @param x1 - {@code int}, X pos 1
        * @param y1 - {@code int}, Y pos 1
        * @param x2 - {@code int}, X pos 2
        * @param y2 - {@code int}, Y pos 2
        * @return {@code int[]} - vector
        */
        public static int[] getVectorForPoints(int x1, int y1, int x2, int y2)
        {
            return new int[] { x2 - x1, y2 - y1 };
        }
        /**
        * Get the angle between two vectors.
        *
        * @param vector1 - {@code int[]}, vector 1
        * @param vector2 - {@code int[]}, vector 2
        * @return {@code double} - angle
        */
        public static double getAngleBetweenVectors(int[] vector1, int[] vector2)
        {
            return Math.atan2(vector2[1], vector2[0]) - Math.atan2(vector1[1], vector1[0]);
        }
    [​IMG]
    Location: the player location
    Direction: the yaw of the player
    Radius: the depth of the cone
    Degrees: Angle between the left and right edge of the cone in degrees

    How this works:
    I get the angle between the vector EntityLocation-PlayerLocation and check it against the vector of LeftEnd-PlayerLocation (Bottom line from player to edge of the circle). If it's smaller than 0 it's not in the cone, because it's left from the left edge of the cone. If it's bigger than 0 and smaller or equal the angle between the left and right edge it's inside it.

    Note: this only checks it in a 2D-space so height is currently ignored.
    If you haven't completely understood it, feel free to ask a question.
     
    tmvkrpxl0, beriere and Limeth like this.
  16. Offline

    caldabeast

    kumpelblase2 Oh god... I don't understand too much of the mathy-math part, but I understand the basics of it. Thanks for the code! You definitely solved my problem!
     
  17. players are able to see others behind them, (you know 2 times f5, or 1 time it when they are close range) you also implementing that? and differend settings of fov?
     
  18. Offline

    caldabeast

    I moreso needed it so that I could check if a hit was a backstab or not. If the player is NOT withing 180degrees of the yaw of the player, then it returns true and BAM insta-kill!
    I like it alot!
     
  19. you know the word lagg, if an player is lagging hard, on his screen he sees n player standing in front of them, but at the connection, there an packets that that player is walking behind him, at the time the server recieves the hit packets, it sees that he is hitting an playe rbehind him, and only bans him for lagg, dont sound fair for me.... (worldedit lagg can also cause it)
     
  20. Offline

    Everdras

    Lag can be discounted. The server would judge backstabs based on the information it has at a specific instant in time. Whether or not the client is up to date with that is the fault of the speed of light and/or the client's connection quality.
     
  21. Offline

    CorrieKay

    ...which can be out of turn.
     
  22. Offline

    Dino Filippini

    "Facestabs" are a commonly known phenomena in Team Fortress 2. The Spy class often relies on being behind it's target to accomplish insta-kills, and even a well programmed and polished game like that has a few quirks that are related to latency and priority in one way or another.

    I'd recommend finding something that works in even the most rudimentary way, and improve from there with proper testing.
     
    caldabeast likes this.
  23. Offline

    md_5

    mbaxter might wanna check that out, since if used for an initial guess it is much faster than a full ray trace.
     
  24. Offline

    Firefly

    kumpelblase2

    I don't get this. I've used it in my code and I'm trying to make it so some code is triggered when a player can't be seen by another player. I'm pretty sure I'm putting in the wrong values for the parameters in the getEntitiesInCone method. Could you explain what should go there? :/

    I get quite variable results with the method proposed by krumpelbase2 using an angle of 120 and a radius of 5. Am I putting in the wrong values for these two parameters? Sometimes it will work fine, but if the target's head budges a little bit, the results get skewed and sometimes inversed :confused: (you will be infront and the code will say you cannot be seen and when you are behind them, it says you can).

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 26, 2016
  25. @Firefly : I have tested it some time ago and it worked all the time. However, I have only tested it in 2d, but since we only use 2d within the code, it shouldn't make any difference.


    The FoV we're checking is always 'the player' 's.
     
  26. Offline

    Firefly

    I'm pretty sure I'm messing up on the degrees parameter. With your testing, what value did you put for that?

    Here's what I have:

    Location: player.getLocation()
    Direction: player.getLocation().getYaw()
    Radius: 5
    Degrees: 120
     
  27. Offline

    Ziden

    i want to know this as well, for sword blocking effects or backstabs ^^ please let me know if someone could do this, im the same as firefly.
     
  28. Offline

    Golui

    Yeah, kumpel's code seems to work only partly. I mean, between certain yaw values. If he could post an example call of his method, that would be much appreciated.
     
  29. Sorry guys, I always forgot to make a reply here because of the coding I'm currently doing.

    However, I can't give you a good example since the values that I put in are either user based or are declared deeply inside the plugin. If you want to see it what so ever, here it is:
    Code:
    Utilities.getPlayersInCone(this.manager.getDungeonByName(this.dungeon).getPlayersWithState(PlayerState.FIGHTER), this.b.getEntity().getLocation(), range, angle, (int)this.b.getEntity().getLocation().getYaw());
    (or see http://www.assembla.com/code/mobdun...BaseClasses/BossAbilityTask.java?rev=78#ln176 for how I implement it.)
    You could think of b.getEntity() as the player who's FoV we are checking. range and angle are user based. I've done a test using - I guess - 5 as range and 90 as angle and it worked fine (player got damaged when he's inside the FoV).

    If it still gives you wrong results, maybe someone wants to play around with it a bit since I can't find a spot where I made a mistake.

    Sorry again for the delay.
    ~kumpelblase2.
     
  30. Offline

    Golui

    Experimented with it a little. Still does not work properly.It seems as it fails to trigger between certain yaw values. Anyone got any luck?
     
Thread Status:
Not open for further replies.

Share This Page