Cancelling a PlayerDeathEvent / Knowing how much damage will be really caused on EntityDamageEvent

Discussion in 'Plugin Development' started by tboss, Jul 4, 2012.

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

    tboss

    Hello, as I could not cancel a PlayerDeathEvent, I use the EntityDamageEvent to prevent the last damage witch causes death.
    But the problem is that if the player wears an armor, the damage returned by event.getDamage() is not the real damage witch would have been inflicted to the player, and so it prevents the damage and teleports the player even if he would not have been dead.
    Any idea to get the real damage witch will be caused to the player, or to cancel a PlayerDeathEvent ?
    Thanks in advance !
     
  2. Offline

    ZeusAllMighty11

    I don't think you can cancel PlayerDeathEvent...


    And maybe you can run a check if the player is wearing armour?
     
  3. Offline

    Milkywayz

    Something like this?
    PHP:
    @EventHandler
    public void onDamage(EntityDamageEvent e ) {
            if(
    e.getEntity() instanceof Player) {
                if(
    e.getDamage() >= ((Playere.getEntity()).getHealth()) {
                    
    e.setDamage(0);
                }
            }
        }
     
  4. Offline

    Cronos79

    if(e.getDamage() >= ((Player) e.getEntity()).getHealth())
    Does not factor armor. If a player hits you with a diamond sharpness 5 sword It will always be true. no matter the armor.

    Im looking for the same thing.
    My plugin what im trying to do is if the player would have died. to instead restore him to full health and put him on the attackers team.

    Took me a day to figure out why even if the player had full health and full armor they were being put on the other team in one shot. and It was the sword was doing 20 damage before armor reduction. e.getDamage is before armor.

    I think i know a way.. hopefully if there is a easier way someone will post before i write all the code lol.

    The only way im seeing right now is to getInvatory each armor then subtract the protection amount from e.getDamage() the do the if statement to check if the damage would kill the player.


    Does anyone have a web link on the math of armor and enchant damage reduction?

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

    Njol

    You also have to take invulnerability into account if you want to be 100% correct ;)
     
  6. Offline

    andf54

    It is impossible to check if the player will die from the damage event.

    You can calculate the damage reduction from enchantments, armour and blocking, but you cant take into account the randomness of the damage. It either randomly rounds up or down, based on which closer.

    One option is to apply the damage yourself instead of letting mc do it. Use a scheduler after a player gets damage, calculate the damage, set event damage so the player doesn’t get killed and after one tick apply the calculated damage.

    Here is how I calculate damage reduction:
    https://github.com/andfRa/Saga/blob/master/src/org/saga/config/VanillaConfiguration.java
    If you are going to use it then tell me if you find any mistakes.
     
    rfsantos1996 likes this.
  7. Offline

    Cronos79

    Thank you for the answer. Im planing on using some type of magic spells plugin also. Sound like it would over complicate things to do that.. Think I'll just let the player die and make him respawn in the right place.
    After I get my plugin working and playable I'll revisit this.
    If I use your code I'll credit you and let you know :)
     
    Vivid1204 likes this.
  8. Offline

    one4me

    tboss
    I tried recreate the NMS code below and it seems to work.
    Code:
    @EventHandler
    public void onEntityDamageEvent(EntityDamageEvent event) {
      Entity entity = event.getEntity();
      if(entity instanceof Player) {
        Player player = (Player)entity;
        if(absoluteHealth(player, event.getDamage(), false) <= 0) {
          event.setCancelled(true);
          player.setHealth(20);
          //Switch teams
        }
      }
    }
    
    /*This method will return the player's remaining health after the specified amount of damage was applied to him/her.*/
    public int absoluteHealth(org.bukkit.entity.Player player, int damage, boolean ignoreArmor) {
      int health = player.getHealth();
      org.bukkit.craftbukkit.entity.CraftPlayer cp = (org.bukkit.craftbukkit.entity.CraftPlayer)player;
      net.minecraft.server.EntityPlayer ep = cp.getHandle();
      if((ep.noDamageTicks > ep.maxNoDamageTicks / 2.0F) && (damage <= ep.lastDamage)) {
        return health;
      }
      int aS = 0;
      boolean invulnerable = false;
      try {
        java.lang.reflect.Field faS = net.minecraft.server.EntityLiving.class.getDeclaredField("aS");
        java.lang.reflect.Field fI = net.minecraft.server.EntityLiving.class.getDeclaredField("invulnerable");
        faS.setAccessible(true);
        fI.setAccessible(true);
        if(faS != null) {
          aS = faS.getInt(ep);
        }
        invulnerable = fI.getBoolean(ep);
      }
      catch(Exception e) {
        e.printStackTrace();
      }
      if(invulnerable) {
        return health;
      }
      if (!ignoreArmor) {
        int j = 25 - ep.aU();
        int k = damage * j + aS;
        damage = k / 25;
        aS = k % 25;
      }
      if(ep.hasEffect(net.minecraft.server.MobEffectList.RESISTANCE)) {
        int j = (ep.getEffect(net.minecraft.server.MobEffectList.RESISTANCE).getAmplifier() + 1) * 5;
        int k = 25 - j;
        int l = damage * k + aS;
        damage = l / 25;
      }
      return health -= damage;
    }
    
    Edit - To anyone else, if you know of an easier way to calculate damage received during an EntityDamageEvent, I'd love to hear it.
     
Thread Status:
Not open for further replies.

Share This Page