Fall damage in fly mode.

Discussion in 'Plugin Development' started by the_merciless, Mar 15, 2013.

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

    the_merciless

    How can I set someone as allowed flight but still have fall damage enabled?
     
  2. Offline

    jorisk322

    I don't think this is possible. You could try disabling flight-ability when someone disables their flight, and set it again when they jump.
     
  3. Offline

    the_merciless

    That would require using playerMoveEevnt which i dont want to do.
     
  4. Offline

    jorisk322

    Then I don't know how it would be done
     
  5. Offline

    Metal Julien

    Wouldn't this work: ?

    Code:
    Listener for PlayerDamage
     
    .
    .
    .
    if (e.getCause == Cause.FALL) {
    if (e.getPlayer().isFlying()) {
    event.setCancelled(true);
     
    }
     
    }
     
  6. Offline

    jorisk322

    No. What you're doing is.. well.. that code wouldn't be noticeable at all.
     
  7. Offline

    chasechocolate

  8. Offline

    the_merciless

    No im trying to add damage, what your doing there is exactly what im trying not to happen.
     
    Metal Julien likes this.
  9. Offline

    lycano

    There is a PlayerToggleFlightEvent so you can check when they toggle it but im currently unsure about the damage as i dont know if you set flymode in survival if it will trigger falldamage when disabling flymode as you usually dont get any damage when disabling it at least in creative.

    Anyways if falldamage does not get triggered when toggling flight to off then the playerdamage event is not fired. Therefore you would have to keep track of their way down to the ground call the PlayerDamageEvent via callEvent and add falldamage by yourself when they hit the highest block under them.

    You would have to do the tracking in PlayerMoveEvent otherwise you wont have any event that can do that. When they toggle themself to no-flymode add them to FallDamager class.

    Create a class called FallDamager that can contain Map<String, Long>. First is the playerName, Long is the highest block below them. Check in PlayerMoveEvent if they are in that Map. If they are you would have to check the Y then for this player eveyrtime they move. If they get to the point of no return add falldamage by yourself. This should minimize the stress to the event as its only for a short amount of time.

    Just add the following code to the PlayerMoveEvent to prevent further processing of that event as we only want to do stuff if they are near the point of no return.

    Add ignoreCancelled=true to the Eventhandler to prevent processing cancelled events.
    Code:
    if (player.getLocation().getY() > fallDamager.getDamagePoint(playerName))
        return;
    
    FallDamager written from mind
    Code:
    public class FallDamager {
     
        protected Map<String, Double> playerList = new HashMap<String, Double>();
     
        public FallDamager() {
        }
     
        public boolean isDamageEnabled(String playerName) {
            return this.playerList.contains(playerName);
        }
     
        public Double getDamagePoint(String playerName) {
            return this.playerList.get(playerName);
        }
     
        public void addDamagee(String playerName) {
            if (this.isDamageEnabled(playerName))
                return;
       
            this.playerList.put(playerName, Bukkit.getPlayerExact(playerName).getLocation().getY());
        }
    }
    
    Edit: Oh, and initialize the FallDamager in your listener class by adding protected FallDamager fallDamager = new FallDamager(); that way you can access it inside the listener cause you obviously dont have to create the class in the event.
     
  10. Offline

    macguy8

    lycano
    Why would you use a Long for the highest block below them? You can use an int for that (and some smaller values)
     
  11. Offline

    lycano

    macguy8 sure thats actually a better approach as you wont really need the precision. You would then have to modify the code so it uses getBlockY() instead of getY(). And as you said Long .. this was my fault you would have to use double instead of long as getY returns double.

    Edited the post.

    Edit: Its getting late .. i read "You can use Integer instead of Long" Anyways you are right. Using Long / Double here is not needed and you can safely use Integer instead.
     
  12. Offline

    the_merciless

    Thanks for the detailed response. If I'm going to use the move event I think it may be easier just to check when they jump. Then add them to allowedFlight. If I was to use a playerMoveEvent on a busy server is it likely to be quite process intensive?
     
  13. Offline

    lycano

    the_merciless ah so you want to let them fly in survival? Well in that case you would have to set flying mode with player.setFlying(true) and false when they are flying otherwise return.

    So you may want to create another class that keeps track of how often they jump. But how you do efficiently detect jumping .. thats currently unknown to me as you cant just track the Y location.

    I would start with spawning an async task and letting it die after 1 sec ~20 ticks. Check if the task is running then spawn another thread that actually would set flying mode to that player.

    As this is kinda complicated i suggest you use PlayerToggleSneakEvent first with the double tab method for the activation as sneaking can be detected easier.

    You can work your way up then and try to find a way out how to do this.

    Some example code ...

    Code:
    public class FlyingPlayer {
     
        protected Map<String, Integer> flyingPlayers = new HashMap<String, Integer>();
     
        public FlyingPlayer() {
        }
     
        public boolean canFly(String playerName) {
            return this.flyingPlayers.contains(playerName);
        }
     
        public void addPlayer(String playerName) {
            this.flyingPlayers.put(playerName, new Integer(1));
        }
     
        public void removePlayer(String playerName) {
            if (this.canFly(playerName))
                this.flyingPlayers.remove(playerName);
        }
    }
    
    I used the integer map cause you can then modify canFly and addPlayer to your needs if you want to let them fly on the third sneak for example. if you dont need that you can just use a simple List<String> for that cause when you added them once the second tab would activate the flymode then when you check for it in PlayerSneakEvent.
     
  14. Offline

    the_merciless

    Not entirely sure if I understand what your saying. My problem is, when I set someone as allowed to fly, they are not necessarily flying. They can be in fly mode yet run around jumping off buildings and not get hurt. I need to activate fly mode as soon as they attempt to fly. Using sneak would mean they have to use tab and then space. And they wouldn't be able to lower themselves with the tab button.
     
  15. Offline

    lycano

    the_merciless Urg yes you are right. Shift is the default key for descending in flymode :S Just forget the last post then. Anyways when you use player.setFlying(true) the player instantly starts flying. setAllowFlight(true) would give them the ability to start flying at any time they double tab space (can be checked with PlayerToggleFlightEvent)

    If you want to have damage enabled when in allowed flight mode running around and not flying you would have to use the FallDamager class and monitor the Y when they are not flying (player.isFlying()) and add the damage by youself.

    This check can only be done in PlayerMoveEvent. What may reduce the stress to the event is that you check if the player did not move.

    add this to your playerListener
    Code:
    private boolean hasChangedBlockCoordinates(final Location fromLoc, final Location toLoc) {
        return !(fromLoc.getWorld().equals(toLoc.getWorld())
                && fromLoc.getBlockX() == toLoc.getBlockX()
                && fromLoc.getBlockY() == toLoc.getBlockY()
                && fromLoc.getBlockZ() == toLoc.getBlockZ());
    }
    
    add this to the move event
    Code:
    if (!this.hasChangedBlockCoordinates(event.getFrom(), event.getTo())) {
        return;
    }
    
     
Thread Status:
Not open for further replies.

Share This Page