3

Inside the for loop I aimed to damage other players that was not damaged. So, I made a new event that has a cause which is suicide so that when it damages the player this method will not be called all over again eventually killing the player. I did my research and found out about calling a new entity damage event EntityDamageEvent e = new EntityDamageEvent(p, DamageCause.SUICIDE,(int)event.getDamage()); Bukkit.getServer().getPluginManager().callEvent(e); to damage the player but it does not seem to work. I need an alternative way to damage my player but not calling this event over and over.

p.Damage(event.getDamage()); When placed inside, the event loops.

@EventHandler
    public void onPlayerDamage(EntityDamageEvent event) {
        if(event.getEntity() instanceof Player && event.getCause() != DamageCause.SUICIDE ) {
            Player damaged =  (Player) event.getEntity();
            for(Player p :Bukkit.getOnlinePlayers()) {
                if(!p.getName().equalsIgnoreCase(damaged.getName())) {
                    EntityDamageEvent e = new EntityDamageEvent(p, DamageCause.SUICIDE,(int)event.getDamage());
                    Bukkit.getServer().getPluginManager().callEvent(e);
                    
                    //double cHealth =p.getHealth()-event.getDamage();
                    //p.setHealth(cHealth);
                }
            }
            
            
        }

The commented code works but when it reaches negative numbers it does not kill the player it only set the players health to a negative number.

  • can you not add something like this to the loop: if (playerHealth <= 0) player.kill; Am I misunderstanding the question? – Nate T Jul 03 '20 at 18:53

2 Answers2

4

Calling the damage event will not damage the player. Events are used to notify a plugin when something happens, the event itself does not make anything happen.

The Damageable#setHealth method does not call the damage event so you can use it without the event being repeatedly called. As the javadocs state, the method will throw an IllegalArgumentException if the health is less than 0 so simply add a check for it.

double cHealth = p.getHealth() - event.getDamage();
p.setHealth(cHealth < 0 ? 0 : cHealth);

However, I do not recommend using the setHealth method because it will not take into account armor. To use the Damageable#damage method without the damage event being repeatedly called you could add the player to a collection and check if the player is in the collection.

private Set<Player> playerSet = new HashSet<>();

@EventHandler
public void onPlayerDamage(EntityDamageEvent event) {
    if (event.getEntity() instanceof Player) {
        Player damaged = (Player) event.getEntity();
        if (!playerSet.contains(damaged)) {
            for (Player p : Bukkit.getOnlinePlayers()) {
                if (!damaged.equals(p)) { 
                    playerSet.add(p);
                    p.damage(event.getDamage());
                }
            }
        } else {
            playerSet.remove(damaged);
        }
    }
}
Donut
  • 405
  • 1
  • 5
  • 12
0

Storing the player to a set is a good idea, but I think you have missed something.

Let's say: player 1 = donut; player 2 = pancake

Assuming that donut takes damage :

damaged = donut
if(!donut.equals(donut))
false
if(!donut.equals(pancake))
true 
   if(!playerSet.contains(pancake))
   true
      playerset.add(pancake);
      pancake.damage(event.getDamage());

We now damaged pancake and stored it in the playerSet Since pancake took damage this event will be called again

damaged = pancake
if (!pancake.equals(donut))
true
   if (!playerSet.contains(donut))
   true 
      playerSet.add(donut);
      donut.damage(event.getDamage());

Then it continues...

Since the damaged player is damaged twice this needs a better solution.

I stumbled upon this solution by adding playerSet.add(damaged);

@EventHandler
    public void onPlayerDamage(EntityDamageEvent event) {
        if(event.getEntity() instanceof Player) {
            Player damaged =  (Player) event.getEntity();
            playerSet.add(damaged);
            for(Player p :Bukkit.getOnlinePlayers()) {
                if(!damaged.equals(p)) {
                    if(!playerSet.contains(p)) {
                        playerSet.add(p);
                        p.damage(event.getDamage());
                    }
                    else {
                        playerSet.remove(p);
                    }
                }
            }   
        }
    }

I still did not check if there are bugs in this code so feel free to point out thanks.