#How to stop fall damage in an event?

1 messages · Page 1 of 1 (latest)

strange frigate
#

I want to make an event that teleports you back up 200 blocks when fallen through void and turns off your fall damage, checks the block under you and sets your hearts to half a heart. How can I implement the turn fall damage off in my event?

        Player player = event.getPlayer();
        if (event.getTo().getBlockY() == 0) {
            player.teleport(player.getLocation().add(0, 200, 0));
            //turn fall damage off

            if (player.getLocation().getBlock().getLocation().equals(-1)) {
                if (player.getLocation().getBlock().getType() != Material.AIR) {
                    player.setHealth(1);
                }
            }
        }
ripe axle
#

Hello!

strange frigate
#

yes! any help?

ripe axle
#

I have one way to do that in my mind right now.

frail dragon
#

Idk if it’s possible to rest fall distance like a method

ripe axle
#

By creating a Set and put player on the Set and then you listen to the EntityDamageEvent, check If the damage is FALL, and then cancel it, and after you cancel it, remove player from the Set.

frail dragon
#

However you could toggle the players fly ability like instantaneously toggle it on and off

strange frigate
#

Ok.. ill try conclure's simpler solution first and see if it works

frail dragon
#

Believe u might have to turn on allow flight

strange frigate
#

wait i think i found a solution

#

if (player.getLastDamageCause().getCause() == EntityDamageEvent.DamageCause.FALL) {

#

now i have to find a way to cancel the event

ripe axle
#

Yeah EntityDamageEvent, just what I said.

#

But you need to create a Set first.

strange frigate
#

idk how to do that

ripe axle
#

Have you ever used a List?

#

Set is basically a same thing as a List.

strange frigate
#

o ok

ripe axle
#

So you create a Set in the field and then when you teleport the player, add the player to the Set.

strange frigate
#

What does the set have to contain?

ripe axle
#

Player object, private final Set<Player> fallenPlayers = new HashSet<>();

strange frigate
#

ok

frail dragon
#

A set is like a list but it should guarantee no duplicates to exist within the same instance. This also means its methods such as contains, add and remove are faster than the similar methods to List, however it entirely depends on implementation.

strange frigate
#

ok cool

ripe axle
#

Thanks for that Conclure.

#

So when you teleport the player 200 blocks above, you add the player to the set.

strange frigate
#

uhm how do i add the player to the set?

ripe axle
#

Set#add(player)

strange frigate
#

it says illegal character '#'

ripe axle
#

This is to detect that the player is being teleported 200 blocks above, so on the EntityDamageEvent we can detect that the player will receive fall damage.

strange frigate
#

shouldnt it be something like fallenPlayers.add(player)

ripe axle
#

Yes, you use . in the code.

strange frigate
ripe axle
#

Change the Set to the variable name.

strange frigate
ripe axle
#

yes

#

exactly like that

strange frigate
#

right now how should i go about cancelling the fall damage event? inside an already existing event?

ripe axle
#

After do that, now you listen to EntityDamageEvent

#

Here's the pseudo code.

  @EventHandler
  public void damageEvent(EntityDamageEvent event){
    if player is inside the Set && damage cause is FALL
      cancel the damage and remove player from the Set
  }
strange frigate
#

ok thank you

ripe axle
#

But first of all, you need to check if the Entity on the event is a Player.

strange frigate
ripe axle
#

Set#contains

strange frigate
#

wait im being dumb

#

i think

#

Player nor player does not work in contains()

#

im using a different class for this event is that why?

ripe axle
#

You can just merge the event to make it simplier.

#

I mean make the event on the same class.

#

I'm guessing you use PlayerMoveEvent for the location check and teleport?

strange frigate
#

yes

ripe axle
#

Yeah so, just move it so it's in the same class.

#

If you want it to be on different classes, take a look at Encapsulation.

strange frigate
ripe axle
#
public class YourClass{

  private final Set<Player> fallenPlayers = new HashSet<>();
  
  @EventHandler
  public void onPlayerMove(PlayerMoveEvent event){
    anything here...
  }

  @EventHandler
  public void onEntityDamage(EntityDamageEvent event){
    anything here...
  }

}
#

So with that, you can access fallenPlayers on both event.

strange frigate
#

yea but i still get an error for checking if the set contains the player e.g. fallenPlayers.contains(Player)

ripe axle
#

What's the error about?

strange frigate
#

*sorry Player with capital

strange frigate
ripe axle
#

You need to get the Player object from the EntityDamageEvent.

strange frigate
#

uhm there is apparently no method for getPlayer(); in EntityDamageEvent

ripe axle
#

Yes, you need to turn getEntity into Player, you can do that by casting it.

#

But first you need to check if the entity is a Player.

strange frigate
#

ohh ok

ripe axle
#

You can do that by doing something like this.

// With this, we will not continue the code if the entity
// is not a player
if(!(event.getEntity() instanceof Player)){
  return;
}
strange frigate
#

oh i said this:

        if (event.getEntityType() == EntityType.PLAYER) {
            Player player = (Player) event.getEntity();
            if (fallenPlayers.contains(player)) {
                event.setDamage(0);
            }
        }
ripe axle
#

Yeah you can do that too.

strange frigate
#

ok cool

ripe axle
#

You can just cancel the event instead set the damage to 0.

#
  1. Check if the damage is FALL
  2. Remove the player from the Set after cancelling the damage.
strange frigate
#

Voila! i hope xD

        if (event.getEntityType() == EntityType.PLAYER) {
            Player player = (Player) event.getEntity();
            if (fallenPlayers.contains(player) && event.getCause() == EntityDamageEvent.DamageCause.FALL) {
                event.setCancelled(true);
                fallenPlayers.remove(player);
            }
        }
ripe axle
#

yup, that's it.

strange frigate
#

right now even if i register the event class to my main class, all the events inside will work right? no registering every event one by one?

ripe axle
#

yes

#

All events inside the class will work.

#

As long as you register the class/listener

strange frigate
#

Alright it worked for the most part, but i want it to set the health of the player to 1 when he lands. I cant check isOnGround() because its deprecated.

ripe axle
#

Set player health after you remove the player from the set.

strange frigate
#

oh wait yea

ripe axle
#

That means the player have reached the ground (when you removes them from the set)

strange frigate
#

Ok it works thank you so much

ripe axle
#

Always happy to help 🙂